Repository: apache/amoro
Pull request #2878 (2024-05-29 09:42:17)

[Hotfix] Optimize code in IcebergTableMaintainer
<!--
Thanks for sending a pull request!

Here are some tips for you:
  1. If this is your first time, please read our contributor guidelines: https://amoro.apache.org/how-to-contribute/
  2. If the PR is related to an issue in https://github.com/apache/amoro/issues, add '[AMORO-XXXX]' in your PR title, e.g., '[AMORO-XXXX] Your PR title ...'.
  3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., '[WIP][AMORO-XXXX] Your PR title ...'.
-->

## Why are the changes needed?

Instants are zoneless, thus it's redundant to adjust the zone of an instant.

## Brief change log
<!--
Clearly describe the changes made in modules, classes, methods, etc.
-->

-

## How was this patch tested?

- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible

- [ ] Add screenshots for manual tests if appropriate

- [ ] Run test locally before making a pull request

## Documentation

- Does this pull request introduce a new feature? (yes / no)
- If yes, how is the feature documented? (not applicable / docs / JavaDocs / not documented)



Patch:
diff --git a/DISCLAIMER b/DISCLAIMER
new file mode 100644
index 000000000..4845ce403
--- /dev/null
+++ b/DISCLAIMER
@@ -0,0 +1,10 @@
+Apache Amoro (incubating) is an effort undergoing incubation at the Apache
+Software Foundation (ASF), sponsored by the Apache Incubator PMC.
+
+Incubation is required of all newly accepted projects until a further review
+indicates that the infrastructure, communications, and decision making process
+have stabilized in a manner consistent with other successful ASF projects.
+
+While incubation status is not necessarily a reflection of the completeness
+or stability of the code, it does indicate that the project has yet to be
+fully endorsed by the ASF.
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 2033ae0cb..4745cbad1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -201,46 +201,4 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 
---------------------------------------------------------------------------------
-
-This product includes code from Apache Iceberg.
-
-* org.apache.iceberg.data.DeleteFilter copied and modified to org.apache.amoro.io.reader.DeleteFilter
-* org.apache.iceberg.deletes.Deletes copied and modified to org.apache.amoro.io.reader.Deletes
-* org.apache.iceberg.data.parquet.BaseParquetReaders copied and modified to org.apache.iceberg.data.parquet.AdaptHiveBaseParquetReaders
-* org.apache.iceberg.data.parquet.BaseParquetWriter copied and modified to org.apache.iceberg.data.parquet.AdaptHiveBaseParquetWriter
-* org.apache.iceberg.data.parquet.GenericParquetReaders copied and modified to org.apache.iceberg.data.parquet.AdaptHiveGenericParquetReaders
-* org.apache.iceberg.data.parquet.GenericParquetWriter copied and modified to org.apache.iceberg.data.parquet.AdaptHiveGenericParquetWriter
-* org.apache.iceberg.data.GenericAppenderFactory copied and modified to org.apache.iceberg.data.AdaptHiveGenericAppenderFactory
-* org.apache.iceberg.parquet.ColumnWriter copied and modified to org.apache.iceberg.parquet.AdaptHiveColumnWriter
-* org.apache.iceberg.parquet.Parquet copied and modified to org.apache.iceberg.parquet.AdaptHiveParquet
-* org.apache.iceberg.parquet.ParquetSchemaUtil copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetSchemaUtil
-* org.apache.iceberg.parquet.ParquetWriter copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetWriter
-* org.apache.iceberg.parquet.PrimitiveWriter copied and modified to org.apache.iceberg.parquet.AdaptHivePrimitiveWriter
-* org.apache.iceberg.parquet.TypeToMessageType copied and modified to org.apache.iceberg.parquet.AdaptHiveTypeToMessageType
-* org.apache.iceberg.parquet.ParquetConversions copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetConversions
-* org.apache.iceberg.parquet.ParquetDictionaryRowGroupFilter copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetDictionaryRowGroupFilter
-* org.apache.iceberg.parquet.ParquetMetricsRowGroupFilter copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetMetricsRowGroupFilter
-* org.apache.iceberg.parquet.ParquetReader copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetReader
-* org.apache.iceberg.parquet.ReadConf copied and modified to org.apache.iceberg.parquet.AdaptHiveReadConf
-* org.apache.iceberg.spark.data.ParquetWithSparkSchemaVisitor copied and modified to org.apache.iceberg.spark.data.AdaptHiveParquetWithSparkSchemaVisitor
-* org.apache.iceberg.flink.data.ParquetWithFlinkSchemaVisitor copied and modified to org.apache.iceberg.flink.data.AdaptHiveParquetWithFlinkSchemaVisitor
-* org.apache.iceberg.parquet.ParquetUtil copied and modified to org.apache.iceberg.parquet.AdaptHiveParquetUtil
-* org.apache.paimon.spark.SparkTypeUtils copied and modified to org.apache.amoro.server.dashboard.component.reverser.PaimonTypeToSparkType
-* org.apache.iceberg.spark.TypeToSparkType copied and modified to org.apache.amoro.server.dashboard.component.reverser.IcebergTypeToSparkType
-
-
-
-Copyright: 2011-2019 The Apache Software Foundation
-Home page: http://iceberg.apache.org/
-License: http://www.apache.org/licenses/LICENSE-2.0
-
---------------------------------------------------------------------------------
-
-This product includes code from Apache Paimon (incubating).
-
-* org.apache.paimon.spark.SparkTypeUtils copied and modified to org.apache.amoro.server.dashboard.component.reverser.PaimonTypeToSparkType
-
-Copyright: 2011-2019 The Apache Software Foundation
-Home page: http://paimon.apache.org/
-License: http://www.apache.org/licenses/LICENSE-2.0
\ No newline at end of file
+--------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
index 8ed060047..d68b086e9 100644
--- a/NOTICE
+++ b/NOTICE
@@ -3,3 +3,12 @@ Copyright 2024 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+Apache Iceberg
+Copyright 2017-2024 The Apache Software Foundation
+
+Apache Paimon
+Copyright 2023-2024 The Apache Software Foundation
+
+Apache Flink
+Copyright 2014-2024 The Apache Software Foundation
\ No newline at end of file
diff --git a/README.md b/README.md
index af1d1ff2b..4c7663a3c 100644
--- a/README.md
+++ b/README.md
@@ -113,7 +113,8 @@ Amoro contains modules as below:
 Amoro is built using Maven with JDK 8 and JDK 17(only for `amoro-mixed-format/amoro-mixed-format-trino` module).
 
 * Build all modules without `amoro-mixed-format-trino`: `mvn clean package`
-* Build and skip tests: `mvn clean package -DskipTests `
+* Build and skip tests: `mvn clean package -DskipTests`
+* Build and skip dashboard: `mvn clean package -Pskip-dashboard-build`
 * Build with hadoop 2.x(the default is 3.x) dependencies: `mvn clean package -DskipTests -Dhadoop=v2`
 * Specify Flink version for Flink optimizer(the default is 1.18.1): `mvn clean package -DskipTests -Dflink-optimizer.flink-version=1.15.4`
   * If the version of Flink is below 1.15.0, you also need to add the `-Pflink-pre-1.15` parameter: `mvn clean package -DskipTests -Pflink-pre-1.15 -Dflink-optimizer.flink-version=1.14.6`
diff --git a/amoro-ams/amoro-ams-dashboard/index.html b/amoro-ams/amoro-ams-dashboard/index.html
index 59910271b..486d18bd1 100644
--- a/amoro-ams/amoro-ams-dashboard/index.html
+++ b/amoro-ams/amoro-ams-dashboard/index.html
@@ -22,7 +22,7 @@
     <meta charset="UTF-8" />
     <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Amoro</title>
+    <title>Apache Amoro™ Dashboard</title>
   </head>
   <body>
     <div id="app"></div>
diff --git a/amoro-ams/amoro-ams-dashboard/pom.xml b/amoro-ams/amoro-ams-dashboard/pom.xml
index 996d25d80..d77c2f859 100644
--- a/amoro-ams/amoro-ams-dashboard/pom.xml
+++ b/amoro-ams/amoro-ams-dashboard/pom.xml
@@ -113,4 +113,22 @@
             </plugin>
         </plugins>
     </build>
+    <profiles>
+        <profile>
+            <id>skip-dashboard-build</id>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>com.github.eirslett</groupId>
+                            <artifactId>frontend-maven-plugin</artifactId>
+                            <configuration>
+                                <skip>true</skip>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/amoro-ams/amoro-ams-dashboard/src/components/sql-editor/index.vue b/amoro-ams/amoro-ams-dashboard/src/components/sql-editor/index.vue
index 8166d6a79..acfd9c543 100644
--- a/amoro-ams/amoro-ams-dashboard/src/components/sql-editor/index.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/components/sql-editor/index.vue
@@ -85,7 +85,16 @@ defineExpose({
   },
   updateOptions(options: any = {}) {
     editor && editor.updateOptions(options)
+  },
+  getSelection() {
+    const selection = editor.getSelection()
+    const model = editor.getModel()
+    if (selection && model) {
+      return model.getValueInRange(selection);
+    }
+    return ''
   }
+
 })
 
 onBeforeUnmount(() => {
diff --git a/amoro-ams/amoro-ams-dashboard/src/services/table.service.ts b/amoro-ams/amoro-ams-dashboard/src/services/table.service.ts
index 8173bf82a..870be9992 100644
--- a/amoro-ams/amoro-ams-dashboard/src/services/table.service.ts
+++ b/amoro-ams/amoro-ams-dashboard/src/services/table.service.ts
@@ -67,7 +67,7 @@ export function getPartitionTable(
     filter: string,
     page: number,
     pageSize: number,
-    token: string
+    token?: string
   }
 ) {
   const { catalog, db, table, filter, page, pageSize, token } = params
@@ -98,7 +98,7 @@ export function getPartitionFiles(
     specId: number,
     page: number
     pageSize: number
-    token: string
+    token?: string
   }
 ) {
   const { catalog, db, table, partition, specId, page, pageSize, token } = params
@@ -144,7 +144,7 @@ export function getOperations(
     table: string,
     page: number
     pageSize: number
-    token: string
+    token?: string
   }
 ) {
   const { catalog, db, table, page, pageSize, token } = params
@@ -158,7 +158,7 @@ export function getOptimizingProcesses(
     table: string,
     page: number
     pageSize: number
-    token: string
+    token?: string
   }
 ) {
   const { catalog, db, table, page, pageSize, token } = params
diff --git a/amoro-ams/amoro-ams-dashboard/src/types/common.type.ts b/amoro-ams/amoro-ams-dashboard/src/types/common.type.ts
index adc2a5f56..8efbab7fb 100644
--- a/amoro-ams/amoro-ams-dashboard/src/types/common.type.ts
+++ b/amoro-ams/amoro-ams-dashboard/src/types/common.type.ts
@@ -70,6 +70,7 @@ export interface IBaseDetailInfo {
 }
 
 export interface DetailColumnItem {
+  checked?: unknown;
   field: string
   type: string
   required: boolean
@@ -206,7 +207,7 @@ export interface ICatalogItem {
   catalogType: string
 }
 export interface IDebugResult {
-  status: number;
+  status: string;
   columns: string[];
   rowData: (string | null)[][];
   id: string
@@ -310,6 +311,7 @@ export interface IOptimizeGroup {
   container: string
   name: string
   properties: IMap<any>
+  innerPropertiesArray?: any[]
 }
 
 export interface IContainerSetting {
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Detail.vue b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Detail.vue
index 6e0735a34..4ed15b085 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Detail.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Detail.vue
@@ -44,7 +44,8 @@ limitations under the License.
             :rules="[{ required: isEdit && isNewCatalog }]">
             <a-checkbox-group :disabled="!isEdit || !isNewCatalog" v-model:value="formState.tableFormatList"
               @change="changeTableFormat">
-              <a-checkbox v-for="item in formatOptions" :key="item" :value="item">{{ tableFormatText[item] }}</a-checkbox>
+              <a-checkbox v-for="item in formatOptions" :key="item" :value="item">{{ tableFormatText[item]
+                }}</a-checkbox>
             </a-checkbox-group>
           </a-form-item>
           <a-form-item :label="$t('optimizerGroup')" :name="['catalog', 'optimizerGroup']"
@@ -76,7 +77,7 @@ limitations under the License.
               class="g-flex-ac">
               <a-upload v-if="isEdit" v-model:file-list="config.fileList" name="file" accept=".xml"
                 :showUploadList="false" :action="uploadUrl" :disabled="config.uploadLoading"
-                @change="(args) => uploadFile(args, config, 'STORAGE')">
+                @change="(args: UploadChangeParam<UploadFile<any>>) => uploadFile(args, config, 'STORAGE')">
                 <a-button type="primary" ghost :loading="config.uploadLoading" class="g-mr-12">{{ $t('upload')
                   }}</a-button>
               </a-upload>
@@ -108,9 +109,10 @@ limitations under the License.
               class="g-flex-ac">
               <a-upload v-if="isEdit" v-model:file-list="config.fileList" name="file"
                 :accept="config.key === 'auth.kerberos.keytab' ? '.keytab' : '.conf'" :showUploadList="false"
-                :action="uploadUrl" :disabled="config.uploadLoading" @change="(args) => uploadFile(args, config)">
-                <a-button type="primary" ghost :loading="config.uploadLoading"
-                  class="g-mr-12">{{ $t('upload') }}</a-button>
+                :action="uploadUrl" :disabled="config.uploadLoading"
+                @change="(args: UploadChangeParam<UploadFile<any>>) => uploadFile(args, config)">
+                <a-button type="primary" ghost :loading="config.uploadLoading" class="g-mr-12">{{ $t('upload')
+                  }}</a-button>
               </a-upload>
               <span v-if="config.isSuccess || config.fileName" class="config-value auth-filename"
                 :class="{ 'view-active': !!config.fileUrl }" @click="viewFileDetail(config.fileUrl)"
@@ -168,6 +170,7 @@ import {
   UploadChangeParam,
   message,
   Modal,
+  UploadFile,
 } from 'ant-design-vue'
 
 interface IStorageConfigItem {
@@ -336,7 +339,7 @@ const getOptimizerGroupList = async () => {
 }
 async function getCatalogTypeOps() {
   const res = await getCatalogsTypes();
-  (res || []).forEach(ele => {
+  (res || []).forEach((ele: any) => {
     if (ele.value !== 'ams') {
       catalogTypeOps.push({
         label: ele.display,
@@ -347,7 +350,7 @@ async function getCatalogTypeOps() {
   getMetastoreType()
 }
 function getMetastoreType() {
-  metastoreType.value = (catalogTypeOps.find(ele => ele.value === formState.catalog.type) || {}).label
+  metastoreType.value = (catalogTypeOps.find(ele => ele.value === formState.catalog.type) || {}).label || ''
 }
 async function getConfigInfo() {
   try {
@@ -356,12 +359,12 @@ async function getConfigInfo() {
     if (!catalogname) { return }
     if (isNewCatalog.value) {
       formState.catalog.name = ''
-      formState.catalog.type = type || 'ams'
+      formState.catalog.type = (type || 'ams') as string
       formState.catalog.optimizerGroup = undefined
       formState.tableFormatList = [tableFormatMap.MIXED_ICEBERG]
       formState.authConfig = { ...newCatalogConfig.authConfig }
       formState.storageConfig = { ...newCatalogConfig.storageConfig }
-      const keys = defaultPropertiesMap[formState.catalog.type] || []
+      const keys = defaultPropertiesMap[formState.catalog.type as keyof typeof defaultPropertiesMap] || []
       formState.properties = {}
       keys.forEach(key => {
         formState.properties[key] = ''
@@ -370,7 +373,7 @@ async function getConfigInfo() {
       formState.storageConfigArray.length = 0
       formState.authConfigArray.length = 0
     } else {
-      const res = await getCatalogsSetting(catalogname)
+      const res = await getCatalogsSetting(catalogname as string)
       if (!res) { return }
       const { name, type, tableFormatList, storageConfig, authConfig, properties, tableProperties, optimizerGroup } = res
       formState.catalog.name = name
@@ -396,10 +399,10 @@ async function getConfigInfo() {
       if (configArr.includes(key)) {
         const item: IStorageConfigItem = {
           key,
-          label: storageConfigMap[key],
-          value: storageConfig[key]?.fileName,
-          fileName: storageConfig[key]?.fileName,
-          fileUrl: storageConfig[key]?.fileUrl,
+          label: storageConfigMap[key as keyof typeof storageConfigMap],
+          value: (storageConfig[key] as any)?.fileName,
+          fileName: (storageConfig[key] as any)?.fileName,
+          fileUrl: (storageConfig[key] as any)?.fileUrl,
           fileId: '',
           fileList: [],
           uploadLoading: false,
@@ -412,10 +415,10 @@ async function getConfigInfo() {
       if (['auth.kerberos.keytab', 'auth.kerberos.krb5'].includes(key)) {
         const item: IStorageConfigItem = {
           key,
-          label: authConfigMap[key],
-          value: authConfig[key]?.fileName,
-          fileName: authConfig[key]?.fileName,
-          fileUrl: authConfig[key]?.fileUrl,
+          label: authConfigMap[key as keyof typeof authConfigMap],
+          value: (authConfig[key] as any)?.fileName,
+          fileName: (authConfig[key] as any)?.fileName,
+          fileUrl: (authConfig[key] as any)?.fileUrl,
           fileId: '',
           fileList: [],
           uploadLoading: false,
@@ -441,20 +444,20 @@ const changeTypeShow = (val: string) => {
 
 const formatOptions = computed(() => {
   const type = formState.catalog.type
-  return storeSupportFormat[type] || []
+  return storeSupportFormat[type as keyof typeof storeSupportFormat] || []
 })
 
 async function changeProperties() {
   const properties = await propertiesRef.value.getPropertiesWithoputValidation()
-  const catalogKeys = defaultPropertiesMap[formState.catalog.type] || []
+  const catalogKeys = defaultPropertiesMap[formState.catalog.type as keyof typeof defaultPropertiesMap] || []
   catalogKeys.forEach(key => {
     if (key && !properties[key]) {
       properties[key] = ''
     }
   })
   const formatKeys = formState.tableFormatList.reduce((accumulator, current) => {
-    return [...accumulator, ...(defaultPropertiesMap[current] || [])]
-  }, [])
+    return [...accumulator, ...(defaultPropertiesMap[current as keyof typeof defaultPropertiesMap] || [])]
+  }, [] as string[])
   formatKeys.forEach(key => {
     if (key && !properties[key]) {
       properties[key] = ''
@@ -547,7 +550,7 @@ function handleEdit() {
   emit('updateEdit', true)
 }
 async function handleRemove() {
-  const res = await checkCatalogStatus(formState.catalog.name)
+  const res = await checkCatalogStatus(formState.catalog.name as string)
   if (res) {
     deleteCatalogModal()
     return
@@ -558,7 +561,7 @@ async function handleRemove() {
     wrapClassName: 'not-delete-modal'
   })
 }
-async function validatorName(rule, value) {
+async function validatorName(_: any, value: string) {
   if (!value) {
     return Promise.reject(new Error(t('inputPlaceholder')))
   }
@@ -573,13 +576,13 @@ function getFileIdParams() {
   Object.keys(authConfig).forEach(key => {
     if (['auth.kerberos.keytab', 'auth.kerberos.krb5'].includes(key)) {
       const id = (authConfigArray.find(item => item.key === key) || {}).fileId
-      authConfig[key] = id
+      authConfig[key as keyof typeof authConfig] = id || ''
     }
   })
   Object.keys(storageConfig).forEach(key => {
     if (['hadoop.core.site', 'hadoop.hdfs.site', 'hive.site'].includes(key)) {
       const id = (storageConfigArray.find(item => item.key === key) || {}).fileId
-      storageConfig[key] = id
+      storageConfig[key as keyof typeof storageConfig] = id || ''
     }
   })
 }
@@ -607,11 +610,11 @@ function handleSave() {
         authConfig,
         properties,
         tableProperties
-      }).then(() => {
+      } as any).then(() => {
         message.success(`${t('save')} ${t('success')}`)
         emit('updateEdit', false, {
-          catalogName: catalog.name,
-          catalogType: catalog.type
+          catalogName: catalog.name || '',
+          catalogType: catalog.type || ''
         })
         getConfigInfo()
         formRef.value.resetFields()
@@ -633,13 +636,13 @@ async function deleteCatalogModal() {
   Modal.confirm({
     title: t('deleteCatalogModalTitle'),
     onOk: async () => {
-      await delCatalog(formState.catalog.name)
+      await delCatalog(formState.catalog.name || '')
       message.success(`${t('remove')} ${t('success')}`)
-      emit('updateEdit', false, {})
+      emit('updateEdit', false)
     }
   })
 }
-function uploadFile(info: UploadChangeParam, config, type?) {
+function uploadFile(info: UploadChangeParam, config: { uploadLoading: boolean; isSuccess: boolean; fileName: any; key: string | number; fileUrl: any; fileId: any }, type?: string) {
   try {
     if (info.file.status === 'uploading') {
       config.uploadLoading = true
@@ -654,7 +657,7 @@ function uploadFile(info: UploadChangeParam, config, type?) {
       }
       const { url, id } = info.file.response.result
       config.isSuccess = true
-      config.fileName = type === 'STORAGE' ? storageConfigFileNameMap[config.key] : info.file.name
+      config.fileName = type === 'STORAGE' ? storageConfigFileNameMap[config.key as keyof typeof storageConfigFileNameMap] : info.file.name
       config.fileUrl = url
       config.fileId = id
       message.success(`${info.file.name} ${t('uploaded')} ${t('success')}`)
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Properties.vue b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Properties.vue
index 7f0f3035e..f16343bc0 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Properties.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/Properties.vue
@@ -1,4 +1,3 @@
-
 <!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
@@ -22,59 +21,40 @@ limitations under the License.
   <div class="config-properties">
     <div v-if="isEdit">
       <div class="config-header g-flex">
-        <div class="td g-flex-ac">{{$t('key')}}</div>
-        <div class="td g-flex-ac bd-left">{{$t('value')}}</div>
+        <div class="td g-flex-ac">{{ $t('key') }}</div>
+        <div class="td g-flex-ac bd-left">{{ $t('value') }}</div>
       </div>
-      <a-form ref="propertiesFormRef" :model="propertiesForm" class="g-mt-12">
+      <a-form ref="propertiesFormRef" layout="inline" :model="propertiesForm" class="g-mt-12">
         <div class="config-row" v-for="(item, index) in propertiesForm.data" :key="item.uuid">
           <!-- validator: validateUnique -->
-          <a-form-item
-            :name="['data', index, 'key']"
-            :rules="[{
-              required: true,
-              message: `${$t(placeholder.inputPh)}`
-            }]"
-            class="g-mr-8"
-          >
-            <a-input
-              v-model:value="item.key"
-              style="width: 100%"
-            />
+          <a-form-item :name="['data', index, 'key']" :rules="rules">
+            <a-input v-model:value="item.key" style="width: 100%" />
           </a-form-item>
-          <a-form-item
-            :name="['data', index, 'value']"
-            :rules="[{
-              required: true,
-              message: `${$t(placeholder.inputPh)}`
-            }]"
-          >
-            <a-input
-              v-model:value="item.value"
-              style="width: 100%"
-            />
+          <a-form-item :name="['data', index, 'value']" :rules="rules">
+            <a-input v-model:value="item.value" style="width: 100%" />
           </a-form-item>
-          <close-outlined class="icon-close" @click="removeRule(item)"  />
+          <close-outlined class="icon-close" @click="removeRule(item)" />
         </div>
       </a-form>
       <a-button class="config-btn" @click="addRule">+</a-button>
     </div>
-    <a-table
-      v-if="!isEdit"
-      rowKey="uuid"
-      :columns="propertiesColumns"
-      :data-source="propertiesForm.data"
-      :pagination="false"
-    ></a-table>
+    <a-table v-if="!isEdit" rowKey="uuid" :columns="propertiesColumns" :data-source="propertiesForm.data"
+      :pagination="false"></a-table>
   </div>
 </template>
 
 <script setup lang="ts">
-import { computed, onMounted, reactive, ref, shallowReactive, watch } from 'vue'
+import { computed, reactive, ref, shallowReactive, watch } from 'vue'
 import { IMap } from '@/types/common.type'
 import { getUUid } from '@/utils/index'
-import { usePlaceholder } from '@/hooks/usePlaceholder'
 import { useI18n } from 'vue-i18n'
 
+interface Propertie {
+  key: string
+  value: string
+  uuid: string
+}
+
 const { t } = useI18n()
 const props = defineProps<{ propertiesObj: IMap<string>, isEdit: boolean }>()
 const propertiesColumns = shallowReactive([
@@ -82,10 +62,14 @@ const propertiesColumns = shallowReactive([
   { dataIndex: 'value', title: t('value'), ellipsis: true }
 ])
 const propertiesFormRef = ref()
-const propertiesForm = reactive<IMap<string>>({
+const propertiesForm = reactive<{ data: Propertie[] }>({
   data: []
 })
-const placeholder = reactive(usePlaceholder())
+
+const rules = [{
+  required: true,
+  message: ``
+}]
 
 const isEdit = computed(() => props.isEdit)
 
@@ -107,7 +91,7 @@ function initPropertiesArray() {
   })
 }
 
-function removeRule(item) {
+function removeRule(item: Propertie) {
   const index = propertiesForm.data.indexOf(item)
   if (index !== -1) {
     propertiesForm.data.splice(index, 1)
@@ -156,81 +140,77 @@ defineExpose({
   }
 })
 
-onMounted(() => {
-})
-
 </script>
 
 <style lang="less">
-  .config-properties {
+.config-properties {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  line-height: 32px;
+
+  .config-header {
     width: 100%;
-    display: flex;
-    flex-direction: column;
-    line-height: 32px;
-    .config-header {
-      width: 100%;
-      padding-right: 32px;
-      background: #fafafa;
-      border-bottom: 1px solid #e8e8f0;
-      .td {
-        width: 50%;
-        height: 40px;
-        padding: 8px 12px;
-        color: #102048;
-        font-weight: 500;
-      }
-      .bd-left {
-        position: relative;
-        &:before {
-          position: absolute;
-          top: 50%;
-          left: 0;
-          width: 1px;
-          height: 1.6em;
-          background-color: rgba(0, 0, 0, 0.06);
-          transform: translateY(-50%);
-          transition: background-color 0.3s;
-          content: '';
-        }
-      }
+    padding-right: 32px;
+    background: #fafafa;
+    border-bottom: 1px solid #e8e8f0;
+
+    .td {
+      width: 50%;
+      height: 40px;
+      padding: 8px 12px;
+      color: #102048;
+      font-weight: 500;
     }
-    .config-row {
-      gap: 10px;
-      display: flex;
-      // height: 40px;
+
+    .bd-left {
       position: relative;
-      padding-right: 32px;
-      width: 100%;
-      .ant-form-item {
-        width: 50%;
-      }
-      .ant-select-auto-complete {
-        width: 50%;
-        input {
-          color: #79809a;
-        }
-      }
-      .ant-input {
-        width: 50%;
-      }
-      .icon-close {
-        cursor: pointer;
+
+      &:before {
         position: absolute;
-        right: 8px;
-        top: 12px;
-        font-size: 12px;
-        &.disabled {
-          cursor: not-allowed;
-        }
+        top: 50%;
+        left: 0;
+        width: 1px;
+        height: 1.6em;
+        background-color: rgba(0, 0, 0, 0.06);
+        transform: translateY(-50%);
+        transition: background-color 0.3s;
+        content: '';
       }
     }
-    .config-btn {
-      border-radius: 4px;
-      width: 100%;
-      border: 1px solid #e5e5e5;
-      text-align: center;
-      color: #102048;
-      box-shadow: none;
+  }
+
+  .config-row {
+    gap: 10px;
+    display: flex;
+    position: relative;
+    padding-right: 10px;
+    width: 100%;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .ant-form-item {
+      flex: 1;
+      margin: 0px !important;
+    }
+
+    .icon-close {
+      cursor: pointer;
+      font-size: 12px;
+
+      &.disabled {
+        cursor: not-allowed;
+      }
     }
   }
+
+  .config-btn {
+    border-radius: 4px;
+    width: 100%;
+    border: 1px solid #e5e5e5;
+    text-align: center;
+    color: #102048;
+    box-shadow: none;
+  }
+}
 </style>
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/index.vue b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/index.vue
index 8ad04da24..2f7991621 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/catalogs/index.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/catalogs/index.vue
@@ -49,7 +49,10 @@ const { t } = useI18n()
 const router = useRouter()
 const route = useRoute()
 const catalogs = reactive<ICatalogItem[]>([])
-const curCatalog = reactive<ICatalogItem>({})
+const curCatalog = reactive<ICatalogItem>({
+  catalogName: '',
+  catalogType: ''
+})
 const isEdit = ref<boolean>(false)
 const NEW_CATALOG = 'new catalog'
 const loading = ref<boolean>(false)
@@ -72,14 +75,17 @@ async function getCatalogs() {
 }
 function initSelectCatalog() {
   const { catalogname = '', type } = route.query
-  const item: ICatalogItem = {}
+  const item: ICatalogItem = {
+    catalogName: '',
+    catalogType: ''
+  }
   if (decodeURIComponent(catalogname as string) === NEW_CATALOG) {
     addCatalog()
     return
   }
   if (catalogname) {
-    item.catalogName = catalogname
-    item.catalogType = type
+    item.catalogName = catalogname as string
+    item.catalogType = type as string
   } else {
     item.catalogName = catalogs[0]?.catalogName
     item.catalogType = catalogs[0]?.catalogType
@@ -110,7 +116,7 @@ async function selectCatalog(item: ICatalogItem) {
   })
 }
 
-async function updateEdit(val, catalog?) {
+async function updateEdit(val: boolean, catalog?: ICatalogItem | undefined) {
   isEdit.value = val
   if (catalog) {
     await updateCatalogs()
@@ -156,7 +162,7 @@ onMounted(async() => {
   await getCatalogs()
   initSelectCatalog()
 })
-function leaveConfirm(cb?) {
+function leaveConfirm(cb?: () => void) {
   Modal.confirm({
     title: t('leavePageModalTitle'),
     content: t('leavePageModalContent'),
@@ -166,7 +172,7 @@ function leaveConfirm(cb?) {
     }
   })
 }
-onBeforeRouteLeave((to, form, next) => {
+onBeforeRouteLeave((_to, _form, next) => {
   if (isEdit.value) {
     leaveConfirm(() => {
       next()
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Field.vue b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Field.vue
index 58be2b164..ed35b4813 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Field.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Field.vue
@@ -58,7 +58,3 @@ defineExpose({
 })
 
 </script>
-<style lang="less" scoped>
-.field-wrap {
-}
-</style>
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Properties.vue b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Properties.vue
index 6c0117f4b..77ebd2392 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Properties.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/components/Properties.vue
@@ -38,7 +38,7 @@ limitations under the License.
           <a-auto-complete
             v-model:value="item.key"
             :options="options"
-            @select="(val, option) => onSelect(val, option, item)"
+            @select="(val:any, option: any) => onSelect(val, option, item)"
             :filter-option="filterOption"
             style="width: 100%"
             class="g-mr-12"
@@ -87,8 +87,8 @@ const propertiesArray = reactive<IItem[]>([])
 const options = ref<IMap<string>[]>()
 const propertiesIncludeValueList = reactive<IKeyAndValue[]>([]) // includes key value
 const propertiesFormRef = ref()
-const propertiesForm = reactive<IMap<string>>({
-  data: []
+const propertiesForm = reactive<IMap<any[]>>({
+  'data': []
 })
 const placeholder = reactive(usePlaceholder())
 
@@ -123,7 +123,7 @@ async function getPropertiesList() {
       text: result[key] || ''
     }
     propertiesIncludeValueList.push(item)
-    options.value.push(item)
+    options.value?.push(item)
   })
 }
 
@@ -131,16 +131,16 @@ function filterOption(input: string, option: IMap<string>) {
   return option.key.toUpperCase().indexOf(input.toUpperCase()) >= 0
 }
 
-function onSelect(val, option, item) {
+function onSelect(_val: any, option: { key: any }, item: { uuid: string }) {
   const key = option.key
   const selected = propertiesIncludeValueList.find((ele: IKeyAndValue) => ele.key === key)
   const selectVal = propertiesForm.data.find((ele: IItem) => ele.uuid === item.uuid)
   if (selectVal) {
-    selectVal.value = selected.text || ''
-    selectVal.key = selected.key || ''
+    selectVal.value = selected?.value || ''
+    selectVal.key = selected?.key || ''
   }
 }
-function removeRule(item) {
+function removeRule(item: any) {
   const index = propertiesForm.data.indexOf(item)
   if (index !== -1) {
     propertiesForm.data.splice(index, 1)
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/upgrade.vue b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/upgrade.vue
index f938d6e40..5a98e9edc 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/hive-details/upgrade.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/hive-details/upgrade.vue
@@ -59,7 +59,7 @@ limitations under the License.
 
 <script lang="ts" setup>
 import { computed, onMounted, reactive, ref } from 'vue'
-import { useRoute, useRouter } from 'vue-router'
+import { useRoute } from 'vue-router'
 import schemaField from './components/Field.vue'
 import partitionField from './components/Partition.vue'
 import otherProperties from './components/Properties.vue'
@@ -120,10 +120,8 @@ function onCofirm() {
 async function getParams() {
   pkName.length = 0
   const pkList = schemaFieldRef.value.getPkname()
-  pkList.forEach((ele: DetailColumnItem) => {
-    pkName.push(ele)
-  })
-  propertiesRef.value.getProperties().then((res) => {
+  pkList.forEach((ele: DetailColumnItem) => pkName.push(ele as any))
+  propertiesRef.value.getProperties().then((res: any) => {
     if (res) {
       Object.assign(propertiesObj, res)
       upgradeTable()
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/optimize/components/List.vue b/amoro-ams/amoro-ams-dashboard/src/views/optimize/components/List.vue
index c2ccc2ed1..778500261 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/optimize/components/List.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/optimize/components/List.vue
@@ -37,7 +37,7 @@ limitations under the License.
           </span>
         </template>
         <template v-if="column.dataIndex === 'optimizeStatus'">
-          <span :style="{ 'background-color': (STATUS_CONFIG[record.optimizeStatus] || {}).color }"
+          <span :style="{ 'background-color': (STATUS_CONFIG[record.optimizeStatus as keyof typeof STATUS_CONFIG] as any)?.color }"
             class="status-icon"></span>
           <span>{{ record.optimizeStatus }}</span>
         </template>
@@ -116,13 +116,13 @@ async function getTableList() {
       page: pagination.current,
       pageSize: pagination.pageSize
     }
-    const result = await getOptimizerTableList(params)
+    const result = await getOptimizerTableList(params as any)
     const { list, total } = result
     pagination.total = total;
     (list || []).forEach((p: IOptimizeTableItem) => {
       p.quotaOccupationDesc = p.quotaOccupation - 0.0005 > 0 ? `${(p.quotaOccupation * 100).toFixed(1)}%` : '0'
-      p.durationDesc = formatMS2Time(p.duration || 0)
-      p.durationDisplay = formatMS2DisplayTime(p.duration || 0)
+      p.durationDesc = formatMS2Time(p.duration || 0) as string
+      (p as any).durationDisplay = formatMS2DisplayTime(p.duration || 0)
       p.fileSizeDesc = bytesToSize(p.fileSize)
       dataSource.push(p)
     })
@@ -132,7 +132,7 @@ async function getTableList() {
   }
 }
 
-function releaseModal(record: IOptimizeResourceTableItem) {
+function releaseModal(record: any) {
   if (record.container === 'external') {
     return
   }
@@ -151,7 +151,7 @@ async function releaseJob(record: IOptimizeResourceTableItem) {
     releaseLoading.value = true
     await releaseResource({
       optimizerGroup: record.groupName,
-      jobId: record.jobId
+      jobId: record.jobId as unknown as string
     })
     refresh(true)
   } finally {
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/resource/components/List.vue b/amoro-ams/amoro-ams-dashboard/src/views/resource/components/List.vue
index 8fa136257..ffee609db 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/resource/components/List.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/resource/components/List.vue
@@ -27,7 +27,7 @@ limitations under the License.
           </span>
         </template>
         <template v-if="column.dataIndex === 'optimizeStatus'">
-          <span :style="{ 'background-color': (STATUS_CONFIG[record.optimizeStatus] || {}).color }"
+          <span :style="{ 'background-color': (STATUS_CONFIG[record.optimizeStatus as keyof typeof STATUS_CONFIG] as any)?.color }"
             class="status-icon"></span>
           <span>{{ record.optimizeStatus }}</span>
         </template>
@@ -65,15 +65,17 @@ import { mbToSize, dateFormat } from '@/utils'
 
 import { message, Modal } from 'ant-design-vue'
 
-import { useRouter } from 'vue-router'
 import ScaleOut from '@/views/resource/components/ScaleOut.vue'
 
 const { t } = useI18n()
-const router = useRouter()
 
-const props = defineProps<{ curGroupName: string, type: string }>()
+const props = defineProps<{ curGroupName?: string, type: string }>()
 
-const emit = defineEmits<{ (e: 'editGroup', record: IIOptimizeGroupItem): void; (e: 'refresh'): void }>()
+const emit = defineEmits<{
+  (e: 'editGroup', record: IIOptimizeGroupItem): void;
+  (e: 'refresh'): void
+  (e: 'refreshCurGroupInfo'): void
+}>()
 
 const STATUS_CONFIG = shallowReactive({
   pending: { title: 'pending', color: '#ffcc00' },
@@ -127,7 +129,7 @@ function refresh(resetPage?: boolean) {
   }
 }
 
-function releaseModal(record: IOptimizeResourceTableItem) {
+function releaseModal(record: any) {
   if (record.container === 'external') {
     return
   }
@@ -220,7 +222,18 @@ const removeGroup = async (record: IIOptimizeGroupItem) => {
   })
 }
 
-const groupRecord = ref({})
+const groupRecord = ref<IIOptimizeGroupItem>({
+  resourceGroup: {
+    name: '',
+    container: '',
+    properties: {}
+  },
+  occupationCore: 0,
+  occupationMemory: 0,
+  name: '',
+  container: '',
+  resourceOccupation: ''
+})
 const scaleOutViseble = ref<boolean>(false)
 const scaleOutGroup = (record: IIOptimizeGroupItem) => {
   if (record.container === 'external') {
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/resource/index.vue b/amoro-ams/amoro-ams-dashboard/src/views/resource/index.vue
index 267a56278..299797cd4 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/resource/index.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/resource/index.vue
@@ -109,7 +109,18 @@ export default defineComponent({
       activeTab: 'optimizergroup' as string,
       showGroupModal: false as boolean,
       groupEdit: false,
-      groupEditRecord: {},
+      groupEditRecord: {
+        resourceGroup: {
+          name: '',
+          container: '',
+          properties: {}
+        },
+        occupationCore: 0,
+        occupationMemory: 0,
+        name: '',
+        container: '',
+        resourceOccupation: ''
+      },
       groupKeyCount: 1,
       showTab: false as boolean
     })
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/settings/index.vue b/amoro-ams/amoro-ams-dashboard/src/views/settings/index.vue
index 9070ccb33..92ddae799 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/settings/index.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/settings/index.vue
@@ -82,13 +82,9 @@ const { t } = useI18n()
 const router = useRouter()
 const route = useRoute()
 const loading = ref<boolean>(false)
-const systemSettingArray = reactive<IKeyAndValue>([])
+const systemSettingArray = reactive<IKeyAndValue[]>([])
 const containerSetting = reactive<IContainerSetting[]>([])
-const optimzeGroupColumns: IColumns[] = reactive([
-  { title: t('name'), dataIndex: 'name', width: 340, ellipsis: true },
-  { title: t('propertiesMemory', { type: 'taskmanager' }), dataIndex: 'tmMemory', width: '50%', ellipsis: true },
-  { title: t('propertiesMemory', { type: 'jobmanager' }), dataIndex: 'jmMemory', width: '50%', ellipsis: true }
-])
+
 const basicColumns: IColumns[] = reactive([
   { title: t('key'), dataIndex: 'key', width: 340, ellipsis: true },
   { title: t('value'), dataIndex: 'value' }
@@ -130,17 +126,17 @@ async function getContainersSettingInfo() {
     const res = await getContainersSetting()
     activeKey.value = []
     containerSetting.length = 0;
-    (res || []).forEach((ele, index) => {
+    (res || []).forEach((ele: any, index: number) => {
       ele.propertiesArray = []
       activeKey.value.push(ele.name)
       containerSetting.push(ele)
       Object.keys(ele.properties || {}).forEach(key => {
-        containerSetting[index].propertiesArray.push({
+        containerSetting[index].propertiesArray?.push({
           key: key,
           value: ele.properties[key]
         })
       });
-      (ele.optimizeGroup || []).forEach(group => {
+      (ele.optimizeGroup || []).forEach((group: { innerPropertiesArray: { key: string; value: any }[]; properties: { [x: string]: any } }) => {
         group.innerPropertiesArray = []
         Object.keys(group.properties || {}).forEach(key => {
           group.innerPropertiesArray.push({
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Details.vue b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Details.vue
index cc7eea117..7447adbfa 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Details.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Details.vue
@@ -85,6 +85,7 @@ import { useRoute } from 'vue-router'
 import { DetailColumnItem, IBaseDetailInfo, IColumns, IMap, PartitionColumnItem } from '@/types/common.type'
 import { getTableDetail } from '@/services/table.service'
 import { dateFormat } from '@/utils'
+import { ColumnProps } from 'ant-design-vue/es/table'
 
 const { t } = useI18n()
 const emit = defineEmits<{
@@ -200,7 +201,7 @@ onMounted(() => {
 
 defineExpose({ getTableDetails })
 
-const primaryColumns: IColumns[] = shallowReactive([
+const primaryColumns: ColumnProps[] = shallowReactive([
   { title: t('field'), dataIndex: 'field', width: '30%' },
   { title: t('type'), dataIndex: 'type', width: '20%' },
   { title: t('required'), dataIndex: 'required', width: '20%', customRender: text => String(text?.value) },
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Files.vue b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Files.vue
index b92f03870..a10d2f93c 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Files.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Files.vue
@@ -24,7 +24,7 @@ limitations under the License.
         <a-input-search
           v-model:value="searchKey"
           :placeholder="$t('fileSearchPlaceholder')"
-          @search="(val) => handleSearch(val)"
+          @search="(val: string) => handleSearch(val)"
           style="width: 350px"
         >
           <template #prefix>
@@ -143,7 +143,7 @@ async function getTableInfo() {
       ...sourceData,
       filter: searchKey.value,
       page: pagination.current,
-      pageSize: pagination.pageSize
+      pageSize: pagination.pageSize,
     })
     const { list, total } = result
     pagination.total = total;
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Optimizing.vue b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Optimizing.vue
index 18bf9de73..e44e549f1 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Optimizing.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Optimizing.vue
@@ -43,7 +43,7 @@ limitations under the License.
           </template>
           <template v-if="column.dataIndex === 'status'">
             <div class="g-flex-ac">
-              <span :style="{ 'background-color': (STATUS_CONFIG[record.status] || {}).color }"
+              <span :style="{ 'background-color': (STATUS_CONFIG[record.status as keyof typeof STATUS_CONFIG] || {} as any).color }"
                 class="status-icon"></span>
               <span>{{ record.status }}</span>
               <a-tooltip v-if="record.status === 'FAILED'" placement="topRight" class="g-ml-4"
@@ -98,7 +98,7 @@ limitations under the License.
           </template>
           <template v-if="column.dataIndex === 'status'">
             <div class="g-flex-ac">
-              <span :style="{ 'background-color': (TASK_STATUS_CONFIG[record.status] || {}).color }"
+              <span :style="{ 'background-color': (TASK_STATUS_CONFIG[record.status as keyof typeof TASK_STATUS_CONFIG] || {} as any).color }"
                 class="status-icon"></span>
               <span>{{ record.status }}</span>
               <a-tooltip v-if="record.status === 'FAILED'" placement="topRight" class="g-ml-4"
@@ -130,6 +130,7 @@ import { IColumns, BreadcrumbOptimizingItem } from '@/types/common.type'
 import { getOptimizingProcesses, getTasksByOptimizingProcessId, cancelOptimizingProcess } from '@/services/table.service'
 import { useRoute } from 'vue-router'
 import { bytesToSize, dateFormat, formatMS2Time } from '@/utils/index'
+import { Modal } from 'ant-design-vue'
 
 const hasBreadcrumb = ref<boolean>(false)
 
@@ -233,9 +234,9 @@ async function cancel() {
     onOk: async () => {
       try {
         loading.value = true
-        const result = await cancelOptimizingProcess({
+        await cancelOptimizingProcess({
           ...sourceData,
-          processId: processId.value
+          processId: processId.value?.toString()
         })
         cancelDisabled.value = true
         refresh()
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Selector.vue b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Selector.vue
index 210edd1e6..00af7d978 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Selector.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/tables/components/Selector.vue
@@ -123,13 +123,13 @@ const onChange = (val: string) => {
 }
 
 const getBranchList = async () => {
-  const result = await getBranches(props)
+  const result = await getBranches(props as any)
   branchList.value = (result.list || []).map((l: IServiceBranchItem) => ({ value: l.name, label: l.name, type: branchTypeMap.BRANCH }))
   branchList.value.length && selectObject(branchList.value[0])
 }
 
 const getTagList = async () => {
-  const result = await getTags(props)
+  const result = await getTags(props as any)
   tagList.value = (result.list || []).map((l: IServiceBranchItem) => ({ value: l.name, label: l.name, type: branchTypeMap.TAG }))
 }
 
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/terminal/components/sql-result.vue b/amoro-ams/amoro-ams-dashboard/src/views/terminal/components/sql-result.vue
index e6143ef60..fb64d1fa1 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/terminal/components/sql-result.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/terminal/components/sql-result.vue
@@ -20,7 +20,7 @@ limitations under the License.
 <template>
 <!-- :style="{width: `${innerWidth}px`}" -->
   <div class="sql-result-wrap">
-    <div class="result-status" :style="{background: debugResultBgcMap[status]}">
+    <div class="result-status" :style="{background: debugResultBgcMap[status as keyof typeof debugResultBgcMap]}">
       <template v-if="status === 'Running'">
         <loading-outlined style="color: #1890ff" />
       </template>
@@ -45,9 +45,8 @@ limitations under the License.
         </thead>
         <tbody class="ant-table-tbody">
           <tr v-for="(rowItem, row) in props.info.rowData" :key="row + 1">
-            <td v-for="(val, col) in rowItem" :key="row + val + col" >
-              <!-- :style="{'maxWidth': `${(100 / (props.info.columns.length)) }%`}" -->
-              <span class="td-val" :title="val">{{ val }}</span>
+            <td v-for="(val, col) in rowItem" :key="`${row}${val}${col}`" >
+              <span class="td-val" :title="val || ''">{{ val }}</span>
             </td>
           </tr>
         </tbody>
diff --git a/amoro-ams/amoro-ams-dashboard/src/views/terminal/index.vue b/amoro-ams/amoro-ams-dashboard/src/views/terminal/index.vue
index 35f4da2ad..2f4195ecc 100644
--- a/amoro-ams/amoro-ams-dashboard/src/views/terminal/index.vue
+++ b/amoro-ams/amoro-ams-dashboard/src/views/terminal/index.vue
@@ -121,6 +121,7 @@ import { ICatalogItem, IDebugResult, ILableAndValue, IMap, debugResultBgcMap } f
 import { executeSql, getExampleSqlCode, getJobDebugResult, getLogsResult, getShortcutsList, stopSql, getLastDebugInfo } from '@/services/terminal.service'
 import { getCatalogList } from '@/services/table.service'
 import { usePlaceholder } from '@/hooks/usePlaceholder'
+import { message } from 'ant-design-vue'
 
 interface ISessionInfo {
   sessionId: string
@@ -229,9 +230,12 @@ export default defineComponent({
         showDebug.value = true
         resetResult()
         runStatus.value = 'Running'
+
+        const sqlToExecute = sqlEditorRef.value.getSelection() || sqlSource.value
+
         const res: ISessionInfo = await executeSql({
           catalog: curCatalog.value,
-          sql: sqlSource.value
+          sql: sqlToExecute
         })
         sessionId.value = res.sessionId || '0'
         getLogResult()
diff --git a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/pom.xml b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/pom.xml
index 8ad91d0e6..7b69727c9 100644
--- a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/pom.xml
+++ b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/pom.xml
@@ -155,32 +155,4 @@
             </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>optimizer.spark3.3</id>
-            <activation>
-                <property>
-                    <name>!optimizer.spark</name>
-                </property>
-            </activation>
-            <properties>
-                <spark-optimizer.spark-version>3.3.3</spark-optimizer.spark-version>
-                <spark-optimizer.scala-version>2.12</spark-optimizer.scala-version>
-            </properties>
-        </profile>
-        <profile>
-            <id>optimizer.spark3.2</id>
-            <activation>
-                <property>
-                    <name>optimizer.spark</name>
-                    <value>3.2</value>
-                </property>
-            </activation>
-            <properties>
-                <spark-optimizer.spark-version>3.2.2</spark-optimizer.spark-version>
-                <spark-optimizer.scala-version>2.12</spark-optimizer.scala-version>
-            </properties>
-        </profile>
-    </profiles>
 </project>
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/AmoroManagementConf.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/AmoroManagementConf.java
index b5f63c28b..6c798ce03 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/AmoroManagementConf.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/AmoroManagementConf.java
@@ -356,6 +356,13 @@ public class AmoroManagementConf {
           .defaultValue(30)
           .withDescription("Session timeout in minutes.");
 
+  public static final ConfigOption<String> TERMINAL_SENSITIVE_CONF_KEYS =
+      ConfigOptions.key("terminal.sensitive-conf-keys")
+          .stringType()
+          .defaultValue("")
+          .withDescription(
+              "Comma-separated list of sensitive conf keys used to desensitize related value.");
+
   /** configs of data expiration */
   public static final ConfigOption<Boolean> DATA_EXPIRATION_ENABLED =
       ConfigOptions.key("data-expiration.enabled")
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
index 015249105..67dff3625 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
@@ -209,7 +209,7 @@ public class RestCatalogService extends PersistentBase {
           } else {
             checkUnsupported(
                 !ns.contains("."), "multi-level namespace is not supported, parent: " + ns);
-            checkDatabaseExist(catalog.exist(ns), ns);
+            checkDatabaseExist(catalog.databaseExists(ns), ns);
           }
           return ListNamespacesResponse.builder().addAll(nsLists).build();
         });
@@ -224,7 +224,7 @@ public class RestCatalogService extends PersistentBase {
           Namespace ns = request.namespace();
           checkUnsupported(ns.length() == 1, "multi-level namespace is not supported now");
           String database = ns.level(0);
-          checkAlreadyExists(!catalog.exist(database), "Database", database);
+          checkAlreadyExists(!catalog.databaseExists(database), "Database", database);
           catalog.createDatabase(database);
           return CreateNamespaceResponse.builder().withNamespace(Namespace.of(database)).build();
         });
@@ -410,7 +410,7 @@ public class RestCatalogService extends PersistentBase {
           String ns = ctx.pathParam("namespace");
           Preconditions.checkNotNull(ns, "namespace is null");
           checkUnsupported(!ns.contains("."), "multi-level namespace is not supported");
-          checkDatabaseExist(catalog.exist(ns), ns);
+          checkDatabaseExist(catalog.databaseExists(ns), ns);
           return handler.apply(catalog, ns);
         });
   }
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
index 5fd6a1f18..6067929ef 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
@@ -83,13 +83,13 @@ public class ExternalCatalog extends ServerCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
-    return doAs(() -> unifiedCatalog.exist(database));
+  public boolean databaseExists(String database) {
+    return doAs(() -> unifiedCatalog.databaseExists(database));
   }
 
   @Override
-  public boolean exist(String database, String tableName) {
-    return doAs(() -> unifiedCatalog.exist(database, tableName));
+  public boolean tableExists(String database, String tableName) {
+    return doAs(() -> unifiedCatalog.tableExists(database, tableName));
   }
 
   @Override
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalCatalog.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalCatalog.java
index f8793ebe8..e540c699e 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalCatalog.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalCatalog.java
@@ -51,7 +51,7 @@ public abstract class InternalCatalog extends ServerCatalog {
   }
 
   public void createDatabase(String databaseName) {
-    if (!exist(databaseName)) {
+    if (!databaseExists(databaseName)) {
       doAsTransaction(
           // make sure catalog existed in database
           () ->
@@ -70,7 +70,7 @@ public abstract class InternalCatalog extends ServerCatalog {
   }
 
   public void dropDatabase(String databaseName) {
-    if (exist(databaseName)) {
+    if (databaseExists(databaseName)) {
       doAsTransaction(
           () ->
               doAsExisted(
@@ -177,7 +177,7 @@ public abstract class InternalCatalog extends ServerCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     return getAs(
             TableMetaMapper.class,
             mapper -> mapper.selectDatabase(getMetadata().getCatalogName(), database))
@@ -185,7 +185,7 @@ public abstract class InternalCatalog extends ServerCatalog {
   }
 
   @Override
-  public boolean exist(String database, String tableName) {
+  public boolean tableExists(String database, String tableName) {
     ServerTableIdentifier tableIdentifier =
         getAs(
             TableMetaMapper.class,
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
index a174076f9..43c42c204 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
@@ -118,7 +118,7 @@ public class InternalIcebergCatalogImpl extends InternalCatalog {
 
     Preconditions.checkArgument(
         format == format(), "the catalog only support to create %s table", format().name());
-    if (exist(database, tableName)) {
+    if (tableExists(database, tableName)) {
       throw new AlreadyExistsException(
           "Table " + name() + "." + database + "." + tableName + " already " + "exists.");
     }
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
index fd1c24ff7..917822498 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
@@ -103,7 +103,7 @@ public class MixedHiveCatalogImpl extends InternalCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     try {
       return hiveClientPool.run(
           client -> {
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ServerCatalog.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ServerCatalog.java
index a959b8ea8..48fe6b951 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ServerCatalog.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ServerCatalog.java
@@ -48,9 +48,9 @@ public abstract class ServerCatalog extends PersistentBase {
     this.metadata = metadata;
   }
 
-  public abstract boolean exist(String database);
+  public abstract boolean databaseExists(String database);
 
-  public abstract boolean exist(String database, String tableName);
+  public abstract boolean tableExists(String database, String tableName);
 
   public abstract List<String> listDatabases();
 
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
index e39edd781..db576d253 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
@@ -297,7 +297,7 @@ public class TableController {
     ServerCatalog serverCatalog = tableService.getServerCatalog(catalog);
     Preconditions.checkArgument(offset >= 0, "offset[%s] must >= 0", offset);
     Preconditions.checkArgument(limit >= 0, "limit[%s] must >= 0", limit);
-    Preconditions.checkState(serverCatalog.exist(db, table), "no such table");
+    Preconditions.checkState(serverCatalog.tableExists(db, table), "no such table");
 
     TableIdentifier tableIdentifier = TableIdentifier.of(catalog, db, table);
     Pair<List<OptimizingProcessInfo>, Integer> optimizingProcessesInfo =
@@ -327,7 +327,7 @@ public class TableController {
     ServerCatalog serverCatalog = tableService.getServerCatalog(catalog);
     Preconditions.checkArgument(offset >= 0, "offset[%s] must >= 0", offset);
     Preconditions.checkArgument(limit >= 0, "limit[%s] must >= 0", limit);
-    Preconditions.checkState(serverCatalog.exist(db, table), "no such table");
+    Preconditions.checkState(serverCatalog.tableExists(db, table), "no such table");
 
     TableIdentifier tableIdentifier = TableIdentifier.of(catalog, db, table);
     List<OptimizingTaskInfo> optimizingTaskInfos =
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/IcebergTableMaintainer.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/IcebergTableMaintainer.java
index b90af6c2f..13f429924 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/IcebergTableMaintainer.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/IcebergTableMaintainer.java
@@ -38,7 +38,6 @@ import org.apache.iceberg.DeleteFile;
 import org.apache.iceberg.DeleteFiles;
 import org.apache.iceberg.FileContent;
 import org.apache.iceberg.FileScanTask;
-import org.apache.iceberg.ManifestFile;
 import org.apache.iceberg.ReachableFileUtil;
 import org.apache.iceberg.RewriteFiles;
 import org.apache.iceberg.Schema;
@@ -76,7 +75,6 @@ import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
@@ -244,7 +242,7 @@ public class IcebergTableMaintainer implements TableMaintainer {
       DataExpirationConfig expirationConfig, Types.NestedField field) {
     switch (expirationConfig.getBaseOnRule()) {
       case CURRENT_TIME:
-        return Instant.now().atZone(getDefaultZoneId(field)).toInstant();
+        return Instant.now();
       case LAST_COMMIT_TIME:
         long lastCommitTimestamp = fetchLatestNonOptimizedSnapshotTime(getTable());
         // if the table does not exist any non-optimized snapshots, should skip the expiration
@@ -570,29 +568,14 @@ public class IcebergTableMaintainer implements TableMaintainer {
     Iterable<Snapshot> snapshots = internalTable.snapshots();
     int size = Iterables.size(snapshots);
     LOG.info("{} getRuntime {} snapshots to scan", tableName, size);
-    int cnt = 0;
     for (Snapshot snapshot : snapshots) {
-      cnt++;
-      int before = validFiles.size();
       String manifestListLocation = snapshot.manifestListLocation();
-
       validFiles.add(TableFileUtil.getUriPath(manifestListLocation));
-
-      // valid data files
-      List<ManifestFile> manifestFiles = snapshot.allManifests(internalTable.io());
-      for (ManifestFile manifestFile : manifestFiles) {
-        validFiles.add(TableFileUtil.getUriPath(manifestFile.path()));
-      }
-
-      LOG.info(
-          "{} scan snapshot {}: {} and getRuntime {} files, complete {}/{}",
-          tableName,
-          snapshot.snapshotId(),
-          formatTime(snapshot.timestampMillis()),
-          validFiles.size() - before,
-          cnt,
-          size);
     }
+    // valid data files
+    Set<String> allManifestFiles = IcebergTableUtil.getAllManifestFiles(internalTable);
+    allManifestFiles.forEach(f -> validFiles.add(TableFileUtil.getUriPath(f)));
+
     Stream.of(
             ReachableFileUtil.metadataFileLocations(internalTable, false).stream(),
             ReachableFileUtil.statisticsFilesLocations(internalTable).stream(),
@@ -640,11 +623,6 @@ public class IcebergTableMaintainer implements TableMaintainer {
     return filesToDelete;
   }
 
-  private static String formatTime(long timestamp) {
-    return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault())
-        .toString();
-  }
-
   CloseableIterable<FileEntry> fileScan(
       Table table, Expression dataFilter, DataExpirationConfig expirationConfig) {
     TableScan tableScan = table.newScan().filter(dataFilter).includeColumnStats();
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/MixedTableMaintainer.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/MixedTableMaintainer.java
index 44936cb37..661802ea4 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/MixedTableMaintainer.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/optimizing/maintainer/MixedTableMaintainer.java
@@ -22,13 +22,12 @@ import static org.apache.amoro.utils.MixedTableUtil.BLOB_TYPE_OPTIMIZED_SEQUENCE
 import static org.apache.iceberg.relocated.com.google.common.primitives.Longs.min;
 
 import org.apache.amoro.IcebergFileEntry;
+import org.apache.amoro.TableFormat;
 import org.apache.amoro.api.config.DataExpirationConfig;
 import org.apache.amoro.data.FileNameRules;
-import org.apache.amoro.hive.utils.TableTypeUtil;
 import org.apache.amoro.scan.TableEntriesScan;
 import org.apache.amoro.server.table.TableRuntime;
 import org.apache.amoro.server.utils.HiveLocationUtil;
-import org.apache.amoro.server.utils.IcebergTableUtil;
 import org.apache.amoro.table.BaseTable;
 import org.apache.amoro.table.ChangeTable;
 import org.apache.amoro.table.KeyedTable;
@@ -62,7 +61,6 @@ import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.time.Instant;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -82,40 +80,13 @@ public class MixedTableMaintainer implements TableMaintainer {
 
   private final BaseTableMaintainer baseMaintainer;
 
-  private final Set<String> changeFiles;
-
-  private final Set<String> baseFiles;
-
-  private final Set<String> hiveFiles;
-
   public MixedTableMaintainer(MixedTable mixedTable) {
     this.mixedTable = mixedTable;
     if (mixedTable.isKeyedTable()) {
-      ChangeTable changeTable = mixedTable.asKeyedTable().changeTable();
-      BaseTable baseTable = mixedTable.asKeyedTable().baseTable();
-      changeMaintainer = new ChangeTableMaintainer(changeTable);
-      baseMaintainer = new BaseTableMaintainer(baseTable);
-      changeFiles =
-          Sets.union(
-              IcebergTableUtil.getAllContentFilePath(changeTable),
-              IcebergTableUtil.getAllStatisticsFilePath(changeTable));
-      baseFiles =
-          Sets.union(
-              IcebergTableUtil.getAllContentFilePath(baseTable),
-              IcebergTableUtil.getAllStatisticsFilePath(baseTable));
+      changeMaintainer = new ChangeTableMaintainer(mixedTable.asKeyedTable().changeTable());
+      baseMaintainer = new BaseTableMaintainer(mixedTable.asKeyedTable().baseTable());
     } else {
       baseMaintainer = new BaseTableMaintainer(mixedTable.asUnkeyedTable());
-      changeFiles = new HashSet<>();
-      baseFiles =
-          Sets.union(
-              IcebergTableUtil.getAllContentFilePath(mixedTable.asUnkeyedTable()),
-              IcebergTableUtil.getAllStatisticsFilePath(mixedTable.asUnkeyedTable()));
-    }
-
-    if (TableTypeUtil.isHive(mixedTable)) {
-      hiveFiles = HiveLocationUtil.getHiveLocation(mixedTable);
-    } else {
-      hiveFiles = new HashSet<>();
     }
   }
 
@@ -313,11 +284,6 @@ public class MixedTableMaintainer implements TableMaintainer {
       this.unkeyedTable = unkeyedTable;
     }
 
-    @Override
-    public Set<String> orphanFileCleanNeedToExcludeFiles() {
-      return Sets.union(changeFiles, Sets.union(baseFiles, hiveFiles));
-    }
-
     @Override
     @VisibleForTesting
     void expireSnapshots(long mustOlderThan) {
@@ -344,11 +310,6 @@ public class MixedTableMaintainer implements TableMaintainer {
           fetchLatestFlinkCommittedSnapshotTime(table));
     }
 
-    @Override
-    protected Set<String> expireSnapshotNeedToExcludeFiles() {
-      return Sets.union(baseFiles, hiveFiles);
-    }
-
     @Override
     protected long snapshotsKeepTime(TableRuntime tableRuntime) {
       return tableRuntime.getTableConfiguration().getChangeDataTTLMinutes() * 60 * 1000;
@@ -470,14 +431,24 @@ public class MixedTableMaintainer implements TableMaintainer {
   }
 
   public class BaseTableMaintainer extends IcebergTableMaintainer {
+    private final Set<String> hiveFiles = Sets.newHashSet();
 
     public BaseTableMaintainer(UnkeyedTable unkeyedTable) {
       super(unkeyedTable);
+      if (unkeyedTable.format() == TableFormat.MIXED_HIVE) {
+        hiveFiles.addAll(HiveLocationUtil.getHiveLocation(mixedTable));
+      }
     }
 
     @Override
     public Set<String> orphanFileCleanNeedToExcludeFiles() {
-      return Sets.union(changeFiles, Sets.union(baseFiles, hiveFiles));
+      Set<String> baseFiles = super.orphanFileCleanNeedToExcludeFiles();
+      return Sets.union(baseFiles, hiveFiles);
+    }
+
+    @Override
+    protected Set<String> expireSnapshotNeedToExcludeFiles() {
+      return hiveFiles;
     }
 
     @Override
@@ -513,11 +484,6 @@ public class MixedTableMaintainer implements TableMaintainer {
         return Long.MAX_VALUE;
       }
     }
-
-    @Override
-    protected Set<String> expireSnapshotNeedToExcludeFiles() {
-      return Sets.union(changeFiles, hiveFiles);
-    }
   }
 
   public static class MixedFileEntry extends IcebergTableMaintainer.FileEntry {
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/DefaultTableService.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/DefaultTableService.java
index 19cc357b7..56a46edb4 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/DefaultTableService.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/DefaultTableService.java
@@ -278,7 +278,7 @@ public class DefaultTableService extends StatedPersistentBase implements TableSe
   public boolean tableExist(TableIdentifier tableIdentifier) {
     checkStarted();
     return getServerCatalog(tableIdentifier.getCatalog())
-        .exist(tableIdentifier.getDatabase(), tableIdentifier.getTableName());
+        .tableExists(tableIdentifier.getDatabase(), tableIdentifier.getTableName());
   }
 
   @Override
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
index f66c4224d..35dd797d9 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
@@ -107,6 +107,9 @@ public class TerminalManager {
     String connectorType = catalogConnectorType(catalogMeta);
     applyClientProperties(catalogMeta);
     Configurations configuration = new Configurations();
+    configuration.set(
+        AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS,
+        serviceConfig.get(AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS));
     configuration.setInteger(TerminalSessionFactory.SessionConfigOptions.FETCH_SIZE, resultLimits);
     configuration.set(
         TerminalSessionFactory.SessionConfigOptions.CATALOGS, Lists.newArrayList(catalog));
@@ -364,6 +367,9 @@ public class TerminalManager {
       key = key.substring(factoryPropertiesPrefix.length());
       configuration.setString(key, value);
     }
+    configuration.set(
+        AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS,
+        serviceConfig.get(AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS));
     configuration.set(TerminalSessionFactory.FETCH_SIZE, this.resultLimits);
     factory.initialize(configuration);
     return factory;
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalSessionContext.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalSessionContext.java
index 3e3e22c1b..3725349a0 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalSessionContext.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalSessionContext.java
@@ -19,6 +19,8 @@
 package org.apache.amoro.server.terminal;
 
 import org.apache.amoro.api.config.Configurations;
+import org.apache.amoro.server.AmoroManagementConf;
+import org.apache.amoro.server.dashboard.utils.DesensitizationUtil;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.commons.io.Charsets;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
@@ -30,12 +32,14 @@ import java.io.IOException;
 import java.io.LineNumberReader;
 import java.io.PrintStream;
 import java.io.StringReader;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 public class TerminalSessionContext {
   private static final Logger LOG = LoggerFactory.getLogger(TerminalSessionContext.class);
@@ -48,6 +52,8 @@ public class TerminalSessionContext {
   private volatile ExecutionTask task = null;
   private final TerminalSessionFactory factory;
   private final Configurations sessionConfiguration;
+
+  private final List<String> sensitiveConfKeys;
   private volatile TerminalSession session;
 
   private volatile long lastExecutionTime = System.currentTimeMillis();
@@ -65,6 +71,13 @@ public class TerminalSessionContext {
     this.threadPool = executor;
     this.factory = factory;
     this.sessionConfiguration = sessionConfiguration;
+    this.sensitiveConfKeys =
+        Arrays.stream(
+                sessionConfiguration
+                    .getString(AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS)
+                    .split(","))
+            .map(String::trim)
+            .collect(Collectors.toList());
   }
 
   public String getSessionId() {
@@ -199,8 +212,16 @@ public class TerminalSessionContext {
               executionResult.appendLog("fetch terminal session: " + sessionId);
               executionResult.appendLogs(session.logs());
               for (String key : session.configs().keySet()) {
-                executionResult.appendLog(
-                    "session configuration: " + key + " => " + session.configs().get(key));
+                if (sensitiveConfKeys.contains(key)) {
+                  executionResult.appendLog(
+                      "session configuration: "
+                          + key
+                          + " => "
+                          + DesensitizationUtil.desensitize(session.configs().get(key)));
+                } else {
+                  executionResult.appendLog(
+                      "session configuration: " + key + " => " + session.configs().get(key));
+                }
               }
 
               return execute(session);
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/kyuubi/KyuubiTerminalSessionFactory.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/kyuubi/KyuubiTerminalSessionFactory.java
index 727299f09..3469cb665 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/kyuubi/KyuubiTerminalSessionFactory.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/kyuubi/KyuubiTerminalSessionFactory.java
@@ -37,6 +37,7 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.stream.Collectors;
 
@@ -123,7 +124,7 @@ public class KyuubiTerminalSessionFactory implements TerminalSessionFactory {
     sessionConf.put("jdbc.url", kyuubiJdbcUrl);
     Properties properties = new Properties();
 
-    if (!metaStore.isKerberosAuthMethod()) {
+    if (!metaStore.isKerberosAuthMethod() && Objects.nonNull(metaStore.getHadoopUsername())) {
       properties.put(JdbcConnectionParams.AUTH_USER, metaStore.getHadoopUsername());
       sessionConf.put(JdbcConnectionParams.AUTH_USER, metaStore.getHadoopUsername());
     }
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/local/LocalSessionFactory.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/local/LocalSessionFactory.java
index ea5d355a1..1a685cdc3 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/local/LocalSessionFactory.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/local/LocalSessionFactory.java
@@ -21,6 +21,8 @@ package org.apache.amoro.server.terminal.local;
 import org.apache.amoro.api.config.ConfigOption;
 import org.apache.amoro.api.config.ConfigOptions;
 import org.apache.amoro.api.config.Configurations;
+import org.apache.amoro.server.AmoroManagementConf;
+import org.apache.amoro.server.dashboard.utils.DesensitizationUtil;
 import org.apache.amoro.server.terminal.SparkContextUtil;
 import org.apache.amoro.server.terminal.TerminalSession;
 import org.apache.amoro.server.terminal.TerminalSessionFactory;
@@ -32,10 +34,12 @@ import org.apache.spark.SparkConf;
 import org.apache.spark.sql.SparkSession;
 import org.apache.spark.sql.internal.SQLConf;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 public class LocalSessionFactory implements TerminalSessionFactory {
 
@@ -50,10 +54,16 @@ public class LocalSessionFactory implements TerminalSessionFactory {
 
   SparkSession context = null;
   Configurations conf;
+  List<String> sensitiveConfKeys;
 
   @Override
   public void initialize(Configurations properties) {
     this.conf = properties;
+    this.sensitiveConfKeys =
+        Arrays.stream(
+                properties.getString(AmoroManagementConf.TERMINAL_SENSITIVE_CONF_KEYS).split(","))
+            .map(String::trim)
+            .collect(Collectors.toList());
   }
 
   @Override
@@ -104,7 +114,11 @@ public class LocalSessionFactory implements TerminalSessionFactory {
   private void updateSessionConf(
       SparkSession session, List<String> logs, String key, String value) {
     session.conf().set(key, value);
-    logs.add(key + "  " + value);
+    if (sensitiveConfKeys.contains(key)) {
+      logs.add(key + "  " + DesensitizationUtil.desensitize(value));
+    } else {
+      logs.add(key + "  " + value);
+    }
   }
 
   protected synchronized SparkSession lazyInitContext() {
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/IcebergTableUtil.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/IcebergTableUtil.java
index e95bb1479..c52949d4f 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/IcebergTableUtil.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/IcebergTableUtil.java
@@ -31,14 +31,21 @@ import org.apache.iceberg.ContentFile;
 import org.apache.iceberg.DeleteFile;
 import org.apache.iceberg.FileContent;
 import org.apache.iceberg.FileScanTask;
+import org.apache.iceberg.HasTableOperations;
+import org.apache.iceberg.MetadataTableType;
+import org.apache.iceberg.MetadataTableUtils;
 import org.apache.iceberg.ReachableFileUtil;
 import org.apache.iceberg.Snapshot;
+import org.apache.iceberg.StructLike;
 import org.apache.iceberg.Table;
+import org.apache.iceberg.TableOperations;
 import org.apache.iceberg.TableScan;
 import org.apache.iceberg.io.CloseableIterable;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
 import org.apache.iceberg.relocated.com.google.common.base.Predicate;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.relocated.com.google.common.collect.Sets;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,6 +58,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+/** Util class for iceberg table. */
 public class IcebergTableUtil {
 
   private static final Logger LOG = LoggerFactory.getLogger(IcebergTableUtil.class);
@@ -136,15 +144,52 @@ public class IcebergTableUtil {
             .useSnapshot(internalTable.currentSnapshot().snapshotId())
             .includeFileContent(FileContent.EQUALITY_DELETES, FileContent.POSITION_DELETES)
             .build();
-
-    for (IcebergFileEntry entry : entriesScan.entries()) {
-      ContentFile<?> file = entry.getFile();
-      String path = file.path().toString();
-      if (!deleteFilesPath.contains(path)) {
-        danglingDeleteFiles.add((DeleteFile) file);
+    try (CloseableIterable<IcebergFileEntry> entries = entriesScan.entries()) {
+      for (IcebergFileEntry entry : entries) {
+        ContentFile<?> file = entry.getFile();
+        String path = file.path().toString();
+        if (!deleteFilesPath.contains(path)) {
+          danglingDeleteFiles.add((DeleteFile) file);
+        }
       }
+    } catch (IOException e) {
+      throw new RuntimeException("Error when fetch iceberg entries", e);
     }
 
     return danglingDeleteFiles;
   }
+
+  /**
+   * Fetch all manifest files of an Iceberg Table
+   *
+   * @param table An iceberg table, or maybe base store or change store of mixed-iceberg format.
+   * @return Path set of all valid manifest files.
+   */
+  public static Set<String> getAllManifestFiles(Table table) {
+    Preconditions.checkArgument(
+        table instanceof HasTableOperations, "the table must support table operation.");
+    TableOperations ops = ((HasTableOperations) table).operations();
+
+    Table allManifest =
+        MetadataTableUtils.createMetadataTableInstance(
+            ops,
+            table.name(),
+            table.name() + "#" + MetadataTableType.ALL_MANIFESTS.name(),
+            MetadataTableType.ALL_MANIFESTS);
+
+    Set<String> allManifestFiles = Sets.newConcurrentHashSet();
+    TableScan scan = allManifest.newScan().select("path");
+
+    CloseableIterable<FileScanTask> tasks = scan.planFiles();
+    CloseableIterable<CloseableIterable<StructLike>> transform =
+        CloseableIterable.transform(tasks, task -> task.asDataTask().rows());
+
+    try (CloseableIterable<StructLike> rows = CloseableIterable.concat(transform)) {
+      rows.forEach(r -> allManifestFiles.add(r.get(0, String.class)));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
+    return allManifestFiles;
+  }
 }
diff --git a/amoro-core/src/main/java/org/apache/amoro/AmoroCatalog.java b/amoro-core/src/main/java/org/apache/amoro/AmoroCatalog.java
index 736175e3a..8f51b066c 100644
--- a/amoro-core/src/main/java/org/apache/amoro/AmoroCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/AmoroCatalog.java
@@ -36,7 +36,7 @@ public interface AmoroCatalog {
    * @param database a database name
    * @return true if the database exists, false otherwise
    */
-  boolean exist(String database);
+  boolean databaseExists(String database);
 
   /**
    * Check whether table exists.
@@ -45,7 +45,7 @@ public interface AmoroCatalog {
    * @param table a table name
    * @return true if the table exists, false otherwise
    */
-  boolean exist(String database, String table);
+  boolean tableExists(String database, String table);
 
   /**
    * create database catalog.
diff --git a/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java b/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
index 23edb5bd6..823f90d41 100644
--- a/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
@@ -69,19 +69,19 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     return listDatabases().contains(database);
   }
 
   @Override
-  public boolean exist(String database, String table) {
+  public boolean tableExists(String database, String table) {
     return formatCatalogAsOrder(TableFormat.values())
-        .anyMatch(formatCatalog -> formatCatalog.exist(database, table));
+        .anyMatch(formatCatalog -> formatCatalog.tableExists(database, table));
   }
 
   @Override
   public void createDatabase(String database) {
-    if (exist(database)) {
+    if (databaseExists(database)) {
       throw new AlreadyExistsException("Database: " + database + " already exists.");
     }
 
@@ -90,7 +90,7 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
 
   @Override
   public void dropDatabase(String database) {
-    if (!exist(database)) {
+    if (!databaseExists(database)) {
       throw new NoSuchDatabaseException("Database: " + database + " does not exist.");
     }
     if (!listTables(database).isEmpty()) {
@@ -101,7 +101,7 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
 
   @Override
   public AmoroTable<?> loadTable(String database, String table) {
-    if (!exist(database)) {
+    if (!databaseExists(database)) {
       throw new NoSuchDatabaseException("Database: " + database + " does not exist.");
     }
 
@@ -130,7 +130,7 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
 
   @Override
   public List<TableIDWithFormat> listTables(String database) {
-    if (!exist(database)) {
+    if (!databaseExists(database)) {
       throw new NoSuchDatabaseException("Database: " + database + " does not exist.");
     }
     TableFormat[] formats =
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java b/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
index f4424240d..d99129ed7 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
@@ -59,12 +59,12 @@ public class IcebergCatalog implements FormatCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     return listDatabases().contains(database);
   }
 
   @Override
-  public boolean exist(String database, String table) {
+  public boolean tableExists(String database, String table) {
     TableIdentifier identifier = TableIdentifier.of(database, table);
     return metaStore.doAs(() -> icebergCatalog.tableExists(identifier));
   }
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java b/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
index 8e57d0446..4ed6a9ea6 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
@@ -44,12 +44,12 @@ public class MixedCatalog implements FormatCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     return catalog.listDatabases().contains(database);
   }
 
   @Override
-  public boolean exist(String database, String table) {
+  public boolean tableExists(String database, String table) {
     return catalog.tableExists(TableIdentifier.of(catalog.name(), database, table));
   }
 
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/paimon/PaimonCatalog.java b/amoro-core/src/main/java/org/apache/amoro/formats/paimon/PaimonCatalog.java
index 0b879703c..b795f0332 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/paimon/PaimonCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/formats/paimon/PaimonCatalog.java
@@ -47,12 +47,12 @@ public class PaimonCatalog implements FormatCatalog {
   }
 
   @Override
-  public boolean exist(String database) {
+  public boolean databaseExists(String database) {
     return catalog.databaseExists(database);
   }
 
   @Override
-  public boolean exist(String database, String table) {
+  public boolean tableExists(String database, String table) {
     return catalog.tableExists(Identifier.create(database, table));
   }
 
diff --git a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/FlinkUnifiedCatalog.java b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/FlinkUnifiedCatalog.java
index 21cafc46f..c36e361a7 100644
--- a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/FlinkUnifiedCatalog.java
+++ b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/FlinkUnifiedCatalog.java
@@ -125,7 +125,7 @@ public class FlinkUnifiedCatalog extends AbstractCatalog {
 
   @Override
   public boolean databaseExists(String databaseName) {
-    return unifiedCatalog.exist(databaseName);
+    return unifiedCatalog.databaseExists(databaseName);
   }
 
   @Override
@@ -193,7 +193,7 @@ public class FlinkUnifiedCatalog extends AbstractCatalog {
   @Override
   public boolean tableExists(ObjectPath tablePath) {
     try {
-      return unifiedCatalog.exist(tablePath.getDatabaseName(), tablePath.getObjectName());
+      return unifiedCatalog.tableExists(tablePath.getDatabaseName(), tablePath.getObjectName());
     } catch (NoSuchDatabaseException | NoSuchTableException e) {
       return false;
     }
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
index 213acfcd1..f2c91aa70 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
@@ -33,7 +33,7 @@
     <url>https://amoro.apache.org</url>
 
     <properties>
-        <spark.version>3.2.2</spark.version>
+        <spark.version>3.2.4</spark.version>
         <scala.version>2.12.15</scala.version>
     </properties>
     <dependencies>
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/main/java/org/apache/amoro/spark/SparkUnifiedCatalog.java b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/main/java/org/apache/amoro/spark/SparkUnifiedCatalog.java
index 1fc9cef74..2454811e5 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/main/java/org/apache/amoro/spark/SparkUnifiedCatalog.java
+++ b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/main/java/org/apache/amoro/spark/SparkUnifiedCatalog.java
@@ -126,7 +126,7 @@ public class SparkUnifiedCatalog implements TableCatalog, SupportsNamespaces, Pr
 
   @Override
   public boolean namespaceExists(String[] namespace) {
-    return unifiedCatalog.exist(namespaceToDatabase(namespace));
+    return unifiedCatalog.databaseExists(namespaceToDatabase(namespace));
   }
 
   @Override
@@ -160,7 +160,7 @@ public class SparkUnifiedCatalog implements TableCatalog, SupportsNamespaces, Pr
       unifiedCatalog.dropTable(database, id.getIdentifier().getTableName(), true);
     }
     unifiedCatalog.dropDatabase(database);
-    return !unifiedCatalog.exist(database);
+    return !unifiedCatalog.databaseExists(database);
   }
 
   @Override
@@ -215,7 +215,7 @@ public class SparkUnifiedCatalog implements TableCatalog, SupportsNamespaces, Pr
 
   @Override
   public boolean tableExists(Identifier ident) {
-    return unifiedCatalog.exist(namespaceToDatabase(ident.namespace()), ident.name());
+    return unifiedCatalog.tableExists(namespaceToDatabase(ident.namespace()), ident.name());
   }
 
   @Override
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml b/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
index 2d4331602..57b0ac302 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
@@ -35,7 +35,7 @@
 
     <properties>
         <hive.version>2.3.9</hive.version>
-        <spark.version>3.2.2</spark.version>
+        <spark.version>3.2.4</spark.version>
         <scala.version>2.12.15</scala.version>
     </properties>
 
diff --git a/amoro-mixed-format/amoro-mixed-format-trino/pom.xml b/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
index eebefece9..f26e80fb0 100644
--- a/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
@@ -37,11 +37,11 @@
         <airlift.version>214</airlift.version>
         <airlift-units.version>1.6</airlift-units.version>
         <airlift-slice.version>0.44</airlift-slice.version>
-        <jackson.version>2.13.1</jackson.version>
+        <jackson.version>2.13.5</jackson.version>
         <guice.version>5.1.0</guice.version>
         <inject.version>1</inject.version>
         <servlet-api.version>4.0.1</servlet-api.version>
-        <commons-collections.version>3.2.1</commons-collections.version>
+        <commons-collections.version>3.2.2</commons-collections.version>
         <avro.version>1.10.1</avro.version>
         <jersey.version>1.19.4</jersey.version>
         <guava-retrying.version>2.0.0</guava-retrying.version>
diff --git a/charts/amoro/values.yaml b/charts/amoro/values.yaml
index 46c27c719..7d735110d 100644
--- a/charts/amoro/values.yaml
+++ b/charts/amoro/values.yaml
@@ -172,12 +172,12 @@ amoroConf:
   ##    kyuubiJdbcUrl: jdbc:hive2://127.0.0.1:10009/
 
   ## @param amoroDefaults The value (templated string) is used for conf.yaml file
-  ## ref: https://github.com/apache/amoro/blob/master/dist/src/main/amoro-bin/conf/config.yaml
+  ## ref: https://github.com/apache/amoro/blob/master/amoro-ams/dist/src/main/amoro-bin/conf/config.yaml
   ##
   amoroDefaults: ~
   ##
   ## @param log4j2 The value (templated string) is used for conf/log4j2.xml file
-  ## ref: https://github.com/apache/amoro/blob/master/dist/src/main/amoro-bin/conf/log4j2.xml
+  ## ref: https://github.com/apache/amoro/blob/master/amoro-ams/dist/src/main/amoro-bin/conf/log4j2.xml
   log4j2: ~
 
 ## Configure the container of optimizer that allows you to submit optimizer by AMS
@@ -259,7 +259,7 @@ optimizer:
 
 ## Configure the ingress resource that allows you to access the
 ## Amoro installation. Set up the URL
-## ref: https://kubernetes.io/docs/user-guide/ingress/
+## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
 ##
 ingress:
   ## @param ingress.enabled Enable ingress controller resource for Amoro Dashbord
diff --git a/pom.xml b/pom.xml
index 2f3bbb60a..312664513 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1002,16 +1002,16 @@
                                 <order>,javax,java,\\#</order>
                             </importOrder>
                             <licenseHeader>
-                                <file>copyright.txt</file>
+                                <file>tools/maven/copyright.txt</file>
                             </licenseHeader>
                         </java>
                         <scala>
                             <scalafmt>
                                 <scalaMajorVersion>2.12</scalaMajorVersion>
-                                <file>.scalafmt.conf</file>
+                                <file>tools/maven/scalafmt.conf</file>
                             </scalafmt>
                             <licenseHeader>
-                                <file>copyright.txt</file>
+                                <file>tools/maven/copyright.txt</file>
                             </licenseHeader>
                         </scala>
                     </configuration>
@@ -1030,7 +1030,7 @@
                                 <familyName>Apache License 2.0</familyName>
                             </licenseFamily>
                         </licenseFamilies>
-                        <excludesFile>.rat-excludes</excludesFile>
+                        <excludesFile>tools/maven/rat-excludes</excludesFile>
                     </configuration>
                     <executions>
                         <execution>
@@ -1107,7 +1107,7 @@
                 <guava.version>14.0.1</guava.version>
                 <hive.version>2.3.9</hive.version>
                 <hadoop.version>2.10.2</hadoop.version>
-                <terminal.spark.version>3.2.2</terminal.spark.version>
+                <terminal.spark.version>3.2.4</terminal.spark.version>
                 <terminal.spark.major.version>3.2</terminal.spark.major.version>
             </properties>
         </profile>
diff --git a/copyright.txt b/tools/maven/copyright.txt
similarity index 100%
rename from copyright.txt
rename to tools/maven/copyright.txt
diff --git a/.rat-excludes b/tools/maven/rat-excludes
similarity index 81%
rename from .rat-excludes
rename to tools/maven/rat-excludes
index bf50c10c3..2adde9ed7 100644
--- a/.rat-excludes
+++ b/tools/maven/rat-excludes
@@ -17,4 +17,6 @@ docs/**
 **/node_modules/**
 **/pnpm-lock.yaml
 **/ams-dashboard/dist/**
-**/components.d.ts
\ No newline at end of file
+**/components.d.ts
+tools/maven/rat-excludes
+tools/maven/scalafmt.conf


Test patch:
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
index a3648a9ac..541cf88b9 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
@@ -125,7 +125,7 @@ public class TestInternalIcebergCatalogService extends RestCatalogServiceTestBas
     @AfterEach
     public void clean() {
       nsCatalog.dropTable(identifier);
-      if (serverCatalog.exist(database, table)) {
+      if (serverCatalog.tableExists(database, table)) {
         serverCatalog.dropTable(database, table);
       }
       serverCatalog.dropDatabase(database);
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/catalog/TestServerCatalog.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/catalog/TestServerCatalog.java
index 1aff22ef5..76e1bbd14 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/catalog/TestServerCatalog.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/catalog/TestServerCatalog.java
@@ -70,12 +70,12 @@ public class TestServerCatalog extends TableCatalogTestBase {
 
   @Test
   public void dataBaseExists() {
-    Assert.assertTrue(getServerCatalog().exist(testDatabaseName));
+    Assert.assertTrue(getServerCatalog().databaseExists(testDatabaseName));
   }
 
   @Test
   public void tableExists() {
-    Assert.assertTrue(getServerCatalog().exist(testDatabaseName, testTableName));
+    Assert.assertTrue(getServerCatalog().tableExists(testDatabaseName, testTableName));
   }
 
   @Test
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
index 5c565ecba..750327a5e 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
@@ -74,7 +74,7 @@ public class TestIcebergHadoopOptimizing extends AbstractOptimizingTest {
     if (icebergCatalog != null) {
       icebergCatalog.dropTable(TableIdentifier.of(DATABASE, TABLE), true);
     }
-    if (serverCatalog != null && serverCatalog.exist(DATABASE, TABLE)) {
+    if (serverCatalog != null && serverCatalog.tableExists(DATABASE, TABLE)) {
       serverCatalog.dropTable(DATABASE, TABLE);
     }
   }
@@ -410,7 +410,7 @@ public class TestIcebergHadoopOptimizing extends AbstractOptimizingTest {
         amsEnv.serviceContainer().getTableService().getServerCatalog(catalog);
     if (serverCatalog instanceof InternalCatalog) {
       this.serverCatalog = (InternalCatalog) serverCatalog;
-      if (!this.serverCatalog.exist(DATABASE)) {
+      if (!this.serverCatalog.databaseExists(DATABASE)) {
         this.serverCatalog.createDatabase(DATABASE);
       }
     }
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestOrphanFileClean.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestOrphanFileClean.java
index 90cd6db28..bf464ca58 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestOrphanFileClean.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestOrphanFileClean.java
@@ -28,16 +28,12 @@ import org.apache.amoro.api.ServerTableIdentifier;
 import org.apache.amoro.api.config.TableConfiguration;
 import org.apache.amoro.catalog.BasicCatalogTestHelper;
 import org.apache.amoro.catalog.CatalogTestHelper;
-import org.apache.amoro.data.ChangeAction;
 import org.apache.amoro.server.dashboard.utils.AmsUtil;
 import org.apache.amoro.server.table.TableRuntime;
 import org.apache.amoro.server.table.executor.ExecutorTestBase;
-import org.apache.amoro.table.KeyedTable;
 import org.apache.amoro.table.TableProperties;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.TableFileUtil;
 import org.apache.iceberg.AppendFiles;
-import org.apache.iceberg.DataFile;
 import org.apache.iceberg.GenericBlobMetadata;
 import org.apache.iceberg.GenericStatisticsFile;
 import org.apache.iceberg.Snapshot;
@@ -47,7 +43,6 @@ import org.apache.iceberg.puffin.BlobMetadata;
 import org.apache.iceberg.puffin.Puffin;
 import org.apache.iceberg.puffin.PuffinWriter;
 import org.junit.Assert;
-import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -55,9 +50,7 @@ import org.mockito.Mockito;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.stream.Collectors;
 
 @RunWith(Parameterized.class)
@@ -211,39 +204,6 @@ public class TestOrphanFileClean extends ExecutorTestBase {
     ExecutorTestBase.assertMetadataExists(getMixedTable());
   }
 
-  @Test
-  public void orphanChangeDataFileInBaseClean() {
-    Assume.assumeTrue(isKeyedTable());
-    KeyedTable testKeyedTable = getMixedTable().asKeyedTable();
-    List<DataFile> dataFiles =
-        tableTestHelper()
-            .writeChangeStore(
-                testKeyedTable, 1L, ChangeAction.INSERT, createRecords(1, 100), false);
-    Set<String> pathAll = new HashSet<>();
-    Set<String> fileInBaseStore = new HashSet<>();
-    Set<String> fileOnlyInChangeLocation = new HashSet<>();
-
-    AppendFiles appendFiles = testKeyedTable.asKeyedTable().baseTable().newAppend();
-
-    for (int i = 0; i < dataFiles.size(); i++) {
-      DataFile dataFile = dataFiles.get(i);
-      pathAll.add(TableFileUtil.getUriPath(dataFile.path().toString()));
-      if (i == 0) {
-        appendFiles.appendFile(dataFile).commit();
-        fileInBaseStore.add(TableFileUtil.getUriPath(dataFile.path().toString()));
-      } else {
-        fileOnlyInChangeLocation.add(TableFileUtil.getUriPath(dataFile.path().toString()));
-      }
-    }
-    pathAll.forEach(path -> Assert.assertTrue(testKeyedTable.io().exists(path)));
-
-    MixedTableMaintainer maintainer = new MixedTableMaintainer(getMixedTable());
-    maintainer.cleanContentFiles(System.currentTimeMillis());
-
-    fileInBaseStore.forEach(path -> Assert.assertTrue(testKeyedTable.io().exists(path)));
-    fileOnlyInChangeLocation.forEach(path -> Assert.assertFalse(testKeyedTable.io().exists(path)));
-  }
-
   @Test
   public void notDeleteFlinkTemporaryFile() throws IOException {
     if (isKeyedTable()) {
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestSnapshotExpire.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestSnapshotExpire.java
index dc68c70a1..5fdb79081 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestSnapshotExpire.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/maintainer/TestSnapshotExpire.java
@@ -147,39 +147,6 @@ public class TestSnapshotExpire extends ExecutorTestBase {
     baseTable.updateStatistics().setStatistics(snapshot.snapshotId(), statisticsFile).commit();
   }
 
-  @Test
-  public void testExpiredChangeTableFilesInBase() {
-    Assume.assumeTrue(isKeyedTable());
-    Assume.assumeTrue(isPartitionedTable());
-    KeyedTable testKeyedTable = getMixedTable().asKeyedTable();
-    testKeyedTable.updateProperties().set(TableProperties.BASE_SNAPSHOT_KEEP_MINUTES, "0").commit();
-    testKeyedTable.updateProperties().set(TableProperties.CHANGE_DATA_TTL, "0").commit();
-    List<DataFile> s1Files = insertChangeDataFiles(testKeyedTable, 1);
-    long l = testKeyedTable.changeTable().currentSnapshot().timestampMillis();
-    testKeyedTable.baseTable().newAppend().appendFile(s1Files.get(0)).commit();
-    List<StructLike> partitions =
-        new ArrayList<>(
-            s1Files.stream().collect(Collectors.groupingBy(ContentFile::partition)).keySet());
-    Assert.assertEquals(2, partitions.size());
-
-    StructLikeMap<Long> optimizedSequence =
-        StructLikeMap.create(testKeyedTable.spec().partitionType());
-    optimizedSequence.put(partitions.get(0), 3L);
-    optimizedSequence.put(partitions.get(1), 1L);
-    writeOptimizedSequence(testKeyedTable, optimizedSequence);
-    s1Files.forEach(file -> Assert.assertTrue(testKeyedTable.io().exists(file.path().toString())));
-
-    MixedTableMaintainer tableMaintainer = new MixedTableMaintainer(testKeyedTable);
-    tableMaintainer.getChangeMaintainer().expireFiles(l + 1);
-    // In order to advance the snapshot
-    insertChangeDataFiles(testKeyedTable, 2);
-    tableMaintainer.getChangeMaintainer().expireSnapshots(System.currentTimeMillis());
-
-    Assert.assertEquals(1, Iterables.size(testKeyedTable.changeTable().snapshots()));
-    Assert.assertTrue(testKeyedTable.io().exists(s1Files.get(0).path().toString()));
-    Assert.assertFalse(testKeyedTable.io().exists(s1Files.get(1).path().toString()));
-  }
-
   @Test
   public void testNotExpireFlinkLatestCommit4ChangeTable() {
     Assume.assumeTrue(isKeyedTable());
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/util/TestIcebergTableUtil.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/util/TestIcebergTableUtil.java
new file mode 100644
index 000000000..b8da9ba9a
--- /dev/null
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/util/TestIcebergTableUtil.java
@@ -0,0 +1,134 @@
+/*
+ * 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.amoro.server.util;
+
+import org.apache.amoro.io.IcebergDataTestHelpers;
+import org.apache.amoro.io.MixedDataTestHelpers;
+import org.apache.amoro.mixed.MixedTables;
+import org.apache.amoro.server.utils.IcebergTableUtil;
+import org.apache.amoro.table.MixedTable;
+import org.apache.amoro.table.PrimaryKeySpec;
+import org.apache.amoro.table.TableMetaStore;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.iceberg.ManifestFile;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.Snapshot;
+import org.apache.iceberg.Table;
+import org.apache.iceberg.catalog.Catalog;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.data.Record;
+import org.apache.iceberg.hadoop.HadoopCatalog;
+import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class TestIcebergTableUtil {
+  private static final Schema schema =
+      new Schema(
+          Types.NestedField.required(1, "id", Types.IntegerType.get()),
+          Types.NestedField.required(2, "data", Types.StringType.get()));
+  private static final PrimaryKeySpec keySpec =
+      PrimaryKeySpec.builderFor(schema).addColumn("id").build();
+
+  @TempDir File warehouse;
+
+  public static Stream<Function<Catalog, Table>> testFetchAllTableManifestFiles() {
+    return Stream.of(
+        (catalog) -> newIcebergTable(catalog),
+        catalog -> newMixedTable(catalog, false).asUnkeyedTable(),
+        catalog -> newMixedTable(catalog, true).asKeyedTable().baseTable(),
+        catalog -> newMixedTable(catalog, true).asKeyedTable().changeTable());
+  }
+
+  @ParameterizedTest
+  @MethodSource
+  public void testFetchAllTableManifestFiles(Function<Catalog, Table> tableProvider)
+      throws IOException {
+    HadoopCatalog catalog = new HadoopCatalog(new Configuration(), warehouse.getAbsolutePath());
+    Table table = tableProvider.apply(catalog);
+
+    // prepare snapshots
+    List<Record> records =
+        IntStream.of(1, 100)
+            .boxed()
+            .map(i -> MixedDataTestHelpers.createRecord(schema, i, UUID.randomUUID().toString()))
+            .collect(Collectors.toList());
+    for (Record r : records) {
+      IcebergDataTestHelpers.append(table, Lists.newArrayList(r));
+    }
+    // expected manifest files
+    Set<String> expectManifestFiles =
+        Lists.newArrayList(table.snapshots()).stream()
+            .flatMap(snapshot -> snapshot.allManifests(table.io()).stream())
+            .map(ManifestFile::path)
+            .collect(Collectors.toSet());
+
+    // reload table
+    TableIdentifier identifier = TableIdentifier.parse(table.name());
+    identifier = TableIdentifier.of("db", identifier.name());
+    Table reloadTable = catalog.loadTable(identifier);
+
+    // get all manifest path by util method. assert result is right.
+    Set<String> actualManifestFiles = IcebergTableUtil.getAllManifestFiles(reloadTable);
+    Assertions.assertEquals(expectManifestFiles, actualManifestFiles);
+
+    // Verify that the tested method does not trigger the snapshot's cache logic.
+    List<Snapshot> snapshots = Lists.newArrayList(reloadTable.snapshots());
+    for (Snapshot snapshot : snapshots) {
+      try {
+        Field allManifests = snapshot.getClass().getDeclaredField("allManifests");
+        allManifests.setAccessible(true);
+        Object value = allManifests.get(snapshot);
+        Assertions.assertNull(value);
+      } catch (NoSuchFieldException | IllegalAccessException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  private static Table newIcebergTable(Catalog catalog) {
+    return catalog.createTable(TableIdentifier.of("db", "table"), schema);
+  }
+
+  private static MixedTable newMixedTable(Catalog catalog, boolean withKey) {
+    MixedTables mixedTables = new MixedTables(TableMetaStore.EMPTY, Maps.newHashMap(), catalog);
+    return mixedTables.createTable(
+        org.apache.amoro.table.TableIdentifier.of("cata", "db", "table"),
+        schema,
+        PartitionSpec.unpartitioned(),
+        withKey ? keySpec : PrimaryKeySpec.noPrimaryKey(),
+        Maps.newHashMap());
+  }
+}
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/TestAmoroCatalogBase.java b/amoro-core/src/test/java/org/apache/amoro/formats/TestAmoroCatalogBase.java
index 2e9f2a767..2e1613d55 100644
--- a/amoro-core/src/test/java/org/apache/amoro/formats/TestAmoroCatalogBase.java
+++ b/amoro-core/src/test/java/org/apache/amoro/formats/TestAmoroCatalogBase.java
@@ -76,14 +76,14 @@ public abstract class TestAmoroCatalogBase extends AmoroCatalogTestBase {
   @Test
   public void testExistsDatabase() {
     createDatabase(DB1);
-    Assert.assertTrue(amoroCatalog.exist(DB1));
+    Assert.assertTrue(amoroCatalog.databaseExists(DB1));
   }
 
   @Test
   public void testExistsTable() {
     createDatabase(DB1);
     createTable(DB1, TABLE, new HashMap<>());
-    Assert.assertTrue(amoroCatalog.exist(DB1, TABLE));
+    Assert.assertTrue(amoroCatalog.tableExists(DB1, TABLE));
   }
 
   @Test
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java b/amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
index 7429f4e9c..f1cd08804 100644
--- a/amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
+++ b/amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
@@ -25,6 +25,7 @@ import org.apache.amoro.data.ChangeAction;
 import org.apache.amoro.io.writer.GenericIcebergPartitionedFanoutWriter;
 import org.apache.amoro.io.writer.RecordWithAction;
 import org.apache.amoro.table.TableProperties;
+import org.apache.iceberg.AppendFiles;
 import org.apache.iceberg.FileFormat;
 import org.apache.iceberg.PartitionKey;
 import org.apache.iceberg.PartitionSpec;
@@ -48,6 +49,7 @@ import org.apache.iceberg.util.PropertyUtil;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -63,6 +65,13 @@ public class IcebergDataTestHelpers {
     }
   }
 
+  public static void append(Table table, List<Record> records) throws IOException {
+    WriteResult result = insert(table, records);
+    AppendFiles files = table.newFastAppend();
+    Arrays.stream(result.dataFiles()).forEach(files::appendFile);
+    files.commit();
+  }
+
   public static WriteResult delta(Table table, List<RecordWithAction> records) throws IOException {
     long targetFileSize =
         PropertyUtil.propertyAsLong(
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/SparkTestBase.java b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/SparkTestBase.java
index 51972568f..d0489bb5e 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/SparkTestBase.java
+++ b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/SparkTestBase.java
@@ -96,7 +96,7 @@ public class SparkTestBase {
     try {
       LOG.debug("prepare database for table test: " + database());
       UnifiedCatalog catalog = unifiedCatalog();
-      if (!unifiedCatalog().exist(database())) {
+      if (!unifiedCatalog().databaseExists(database())) {
         catalog.createDatabase(database());
       }
     } catch (AlreadyExistsException e) {
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/unified/UnifiedCatalogTestSuites.java b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/unified/UnifiedCatalogTestSuites.java
index e42f3e13a..6c2b6b286 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/unified/UnifiedCatalogTestSuites.java
+++ b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/src/test/java/org/apache/amoro/spark/test/unified/UnifiedCatalogTestSuites.java
@@ -95,7 +95,7 @@ public class UnifiedCatalogTestSuites extends SparkTestBase {
     testCallProcedure(format);
 
     sql("DROP TABLE " + target() + " PURGE");
-    Assertions.assertFalse(unifiedCatalog().exist(target().database, target().table));
+    Assertions.assertFalse(unifiedCatalog().tableExists(target().database, target().table));
   }
 
   private String pkDDL(TableFormat format) {
@@ -173,7 +173,7 @@ public class UnifiedCatalogTestSuites extends SparkTestBase {
     UnifiedCatalog unifiedCatalog =
         UnifiedCatalogLoader.loadUnifiedCatalog(
             CONTEXT.amsThriftUrl(), format.name().toLowerCase(), Maps.newHashMap());
-    if (!unifiedCatalog().exist(database())) {
+    if (!unifiedCatalog().databaseExists(database())) {
       unifiedCatalog.createDatabase(database());
     }
   }