This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 6fc8f333400 [fix](fe) Improve MaxCompute catalog validation (#64119)
6fc8f333400 is described below

commit 6fc8f3334009f24e464b81ddf8c44e547ebb6eee
Author: daidai <[email protected]>
AuthorDate: Tue Jun 9 16:49:10 2026 +0800

    [fix](fe) Improve MaxCompute catalog validation (#64119)
    
    ### What problem does this PR solve?
    Problem Summary:
    Use the `test_connection` catalog parameter, to perform ak-sk、 project
    、schema validation when creating a maxcompute catalog.
---
 .../doris/datasource/maxcompute/MCTransaction.java |   4 +
 .../maxcompute/MaxComputeExternalCatalog.java      |  70 +++++++++-
 .../maxcompute/MaxComputeExternalTable.java        |  11 ++
 .../maxcompute/source/MaxComputeScanNode.java      |   5 +
 .../datasource/maxcompute/MCTransactionTest.java   |  54 ++++++++
 .../maxcompute/MaxComputeExternalCatalogTest.java  | 146 +++++++++++++++++++++
 .../maxcompute/source/MaxComputeScanNodeTest.java  |  24 ++++
 fe/pom.xml                                         |   2 +-
 .../test_external_catalog_maxcompute.groovy        |   6 +-
 .../maxcompute/test_max_compute_schema.groovy      |   5 +-
 .../test_max_compute_validate_connection.groovy    | 102 ++++++++++++++
 11 files changed, 422 insertions(+), 7 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MCTransaction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MCTransaction.java
index 9f1c61ddf24..6d5a6c9112f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MCTransaction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MCTransaction.java
@@ -71,6 +71,10 @@ public class MCTransaction implements Transaction {
 
     public void beginInsert(ExternalTable dorisTable, 
Optional<InsertCommandContext> ctx) throws UserException {
         this.table = (MaxComputeExternalTable) dorisTable;
+        if (table.isUnsupportedOdpsTable()) {
+            throw new UserException("Writing MaxCompute external table or 
logical view is not supported: "
+                    + table.getDbName() + "." + table.getName());
+        }
 
         try {
             TableIdentifier tableId = 
catalog.getOdpsTableIdentifier(table.getDbName(), table.getName());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalog.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalog.java
index 75cf2d201d6..75a6190d696 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalog.java
@@ -28,6 +28,7 @@ import org.apache.doris.datasource.SessionContext;
 import org.apache.doris.transaction.TransactionManagerFactory;
 
 import com.aliyun.odps.Odps;
+import com.aliyun.odps.OdpsException;
 import com.aliyun.odps.Partition;
 import com.aliyun.odps.account.AccountFormat;
 import com.aliyun.odps.table.TableIdentifier;
@@ -52,7 +53,6 @@ public class MaxComputeExternalCatalog extends 
ExternalCatalog {
 
     // you can ref : https://help.aliyun.com/zh/maxcompute/user-guide/endpoints
     private static final String endpointTemplate = 
"http://service.{}.maxcompute.aliyun-inc.com/api";;
-
     private Map<String, String> props;
     private Odps odps;
     private String endpoint;
@@ -206,6 +206,9 @@ public class MaxComputeExternalCatalog extends 
ExternalCatalog {
         odps = MCUtils.createMcClient(props);
         odps.setDefaultProject(defaultProject);
         odps.setEndpoint(endpoint);
+        odps.getRestClient().setConnectTimeout(connectTimeout);
+        odps.getRestClient().setReadTimeout(readTimeout);
+        odps.getRestClient().setRetryTimes(retryTimes);
 
         String accountFormatProp = 
props.getOrDefault(MCProperties.ACCOUNT_FORMAT, 
MCProperties.DEFAULT_ACCOUNT_FORMAT);
         if (accountFormatProp.equals(MCProperties.ACCOUNT_FORMAT_NAME)) {
@@ -233,6 +236,69 @@ public class MaxComputeExternalCatalog extends 
ExternalCatalog {
         transactionManager = 
TransactionManagerFactory.createMCTransactionManager(this);
     }
 
+    @Override
+    public void checkWhenCreating() throws DdlException {
+        boolean testConnection = 
Boolean.parseBoolean(catalogProperty.getOrDefault(TEST_CONNECTION,
+                String.valueOf(DEFAULT_TEST_CONNECTION)));
+        if (!testConnection) {
+            return;
+        }
+        // MaxCompute has no MetastoreProperties-backed connectivity tester 
yet,
+        // so run its catalog-specific test directly under the common 
test_connection switch.
+        boolean enableNamespaceSchema = Boolean.parseBoolean(
+                
catalogProperty.getOrDefault(MCProperties.ENABLE_NAMESPACE_SCHEMA,
+                        MCProperties.DEFAULT_ENABLE_NAMESPACE_SCHEMA));
+        try {
+            initLocalObjects();
+            validateMaxComputeConnection(enableNamespaceSchema);
+        } catch (Exception e) {
+            throw new DdlException(e.getMessage(), e);
+        }
+    }
+
+    protected void validateMaxComputeConnection(boolean enableNamespaceSchema) 
{
+        if (enableNamespaceSchema) {
+            validateMaxComputeProjectAndNamespaceSchema();
+        } else {
+            validateMaxComputeProject();
+        }
+    }
+
+    private void validateMaxComputeProject() {
+        boolean projectExists;
+        try {
+            projectExists = maxComputeProjectExists(defaultProject);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to validate MaxCompute project 
'" + defaultProject
+                    + "'. Check " + MCProperties.PROJECT + ", " + 
MCProperties.ENDPOINT
+                    + " and credentials. Cause: " + e.getMessage(), e);
+        }
+        if (!projectExists) {
+            throw new RuntimeException("Failed to validate MaxCompute project 
'" + defaultProject
+                    + "'. Check " + MCProperties.PROJECT + ", " + 
MCProperties.ENDPOINT
+                    + " and credentials. Cause: project does not exist or is 
not accessible");
+        }
+    }
+
+    private void validateMaxComputeProjectAndNamespaceSchema() {
+        try {
+            validateMaxComputeNamespaceSchemaAccess(defaultProject);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to validate MaxCompute project 
'" + defaultProject
+                    + "' with namespace schema. Check " + MCProperties.PROJECT 
+ ", " + MCProperties.ENDPOINT
+                    + ", credentials, and whether the schema list is 
accessible for the namespace schema "
+                    + "configuration. Cause: " + e.getMessage(), e);
+        }
+    }
+
+    protected boolean maxComputeProjectExists(String projectName) throws 
OdpsException {
+        return odps.projects().exists(projectName);
+    }
+
+    protected void validateMaxComputeNamespaceSchemaAccess(String projectName) 
throws OdpsException {
+        odps.schemas().iterator(projectName).hasNext();
+    }
+
     public Odps getClient() {
         makeSureInitialized();
         return odps;
@@ -401,7 +467,7 @@ public class MaxComputeExternalCatalog extends 
ExternalCatalog {
                         MCProperties.DEFAULT_SPLIT_BYTE_SIZE));
 
                 if (splitByteSize < 10485760L) {
-                    throw new DdlException(MCProperties.SPLIT_ROW_COUNT + " 
must be greater than or equal to 10485760");
+                    throw new DdlException(MCProperties.SPLIT_BYTE_SIZE + " 
must be greater than or equal to 10485760");
                 }
 
             } else if 
(splitStrategy.equals(MCProperties.SPLIT_BY_ROW_COUNT_STRATEGY)) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalTable.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalTable.java
index 839995ca5f6..ec6e7f79d6d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalTable.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalTable.java
@@ -54,6 +54,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -328,6 +329,16 @@ public class MaxComputeExternalTable extends ExternalTable 
{
                 .orElse(null);
     }
 
+    public boolean isUnsupportedOdpsTable() {
+        Table odpsTable = getOdpsTable();
+        return isUnsupportedOdpsTable(odpsTable);
+    }
+
+    public static boolean isUnsupportedOdpsTable(Table odpsTable) {
+        Objects.requireNonNull(odpsTable, "MaxCompute table metadata is not 
initialized");
+        return odpsTable.isExternalTable() || odpsTable.isVirtualView();
+    }
+
     @Override
     public boolean isPartitionedTable() {
         makeSureInitialized();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
index d79e43aed74..ae297d99c44 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
@@ -707,6 +707,11 @@ public class MaxComputeScanNode extends FileQueryScanNode {
         long getOdpsTableTime = System.currentTimeMillis();
         LOG.info("MaxComputeScanNode getSplits: getOdpsTable cost {} ms", 
getOdpsTableTime - startTime);
 
+        if (MaxComputeExternalTable.isUnsupportedOdpsTable(odpsTable)) {
+            throw new UserException("Reading MaxCompute external table or 
logical view is not supported: "
+                    + table.getDbName() + "." + table.getName());
+        }
+
         if (desc.getSlots().isEmpty() || odpsTable.getFileNum() <= 0) {
             return result;
         }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MCTransactionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MCTransactionTest.java
new file mode 100644
index 00000000000..e76f192a858
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MCTransactionTest.java
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource.maxcompute;
+
+import org.apache.doris.common.UserException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Optional;
+
+public class MCTransactionTest {
+    @Test
+    public void testBeginInsertRejectsOdpsExternalTable() {
+        assertBeginInsertRejectsUnsupportedOdpsTable("mc_external_table");
+    }
+
+    @Test
+    public void testBeginInsertRejectsOdpsLogicalView() {
+        assertBeginInsertRejectsUnsupportedOdpsTable("mc_logical_view");
+    }
+
+    private void assertBeginInsertRejectsUnsupportedOdpsTable(String 
tableName) {
+        MaxComputeExternalCatalog catalog = 
Mockito.mock(MaxComputeExternalCatalog.class);
+        MaxComputeExternalTable table = 
Mockito.mock(MaxComputeExternalTable.class);
+        Mockito.when(table.isUnsupportedOdpsTable()).thenReturn(true);
+        Mockito.when(table.getDbName()).thenReturn("default");
+        Mockito.when(table.getName()).thenReturn(tableName);
+
+        MCTransaction transaction = new MCTransaction(catalog);
+
+        UserException exception = Assert.assertThrows(UserException.class,
+                () -> transaction.beginInsert(table, Optional.empty()));
+        Assert.assertTrue(exception.getMessage().contains(
+                "Writing MaxCompute external table or logical view is not 
supported: default." + tableName));
+        Mockito.verify(catalog, 
Mockito.never()).getOdpsTableIdentifier(Mockito.anyString(), 
Mockito.anyString());
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalogTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalogTest.java
new file mode 100644
index 00000000000..dfe22f136b5
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/MaxComputeExternalCatalogTest.java
@@ -0,0 +1,146 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource.maxcompute;
+
+import org.apache.doris.common.DdlException;
+import org.apache.doris.common.maxcompute.MCProperties;
+import org.apache.doris.datasource.ExternalCatalog;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MaxComputeExternalCatalogTest {
+    @Test
+    public void testSplitByteSizeErrorMessage() {
+        Map<String, String> props = new HashMap<>();
+        addRequiredProperties(props);
+        props.put(MCProperties.SPLIT_STRATEGY, 
MCProperties.SPLIT_BY_BYTE_SIZE_STRATEGY);
+        props.put(MCProperties.SPLIT_BYTE_SIZE, "1048576");
+
+        MaxComputeExternalCatalog catalog = new MaxComputeExternalCatalog(1L, 
"mc_catalog", null, props, "");
+
+        DdlException exception = Assert.assertThrows(DdlException.class, 
catalog::checkProperties);
+        Assert.assertTrue(exception.getMessage().contains(
+                MCProperties.SPLIT_BYTE_SIZE + " must be greater than or equal 
to 10485760"));
+        
Assert.assertFalse(exception.getMessage().contains(MCProperties.SPLIT_ROW_COUNT));
+    }
+
+    @Test
+    public void testCheckWhenCreatingSkipsValidationByDefault() throws 
DdlException {
+        Map<String, String> props = createRequiredProperties(true);
+        TestMaxComputeExternalCatalog catalog = new 
TestMaxComputeExternalCatalog(props);
+
+        catalog.checkWhenCreating();
+
+        Assert.assertNull(catalog.checkedProjectName);
+        Assert.assertNull(catalog.checkedNamespaceSchemaProjectName);
+    }
+
+    @Test
+    public void testCheckWhenCreatingValidatesProjectWhenValidationEnabled() 
throws DdlException {
+        Map<String, String> props = createRequiredProperties(false);
+        props.put(ExternalCatalog.TEST_CONNECTION, "true");
+        TestMaxComputeExternalCatalog catalog = new 
TestMaxComputeExternalCatalog(props);
+
+        catalog.checkWhenCreating();
+
+        Assert.assertEquals("mc_project", catalog.checkedProjectName);
+        Assert.assertNull(catalog.checkedNamespaceSchemaProjectName);
+    }
+
+    @Test
+    public void 
testCheckWhenCreatingValidatesSchemaWhenNamespaceSchemaEnabled() throws 
DdlException {
+        Map<String, String> props = createRequiredProperties(true);
+        props.put(ExternalCatalog.TEST_CONNECTION, "true");
+        TestMaxComputeExternalCatalog catalog = new 
TestMaxComputeExternalCatalog(props);
+
+        catalog.checkWhenCreating();
+
+        Assert.assertNull(catalog.checkedProjectName);
+        Assert.assertEquals("mc_project", 
catalog.checkedNamespaceSchemaProjectName);
+    }
+
+    @Test
+    public void testCheckWhenCreatingReportsInaccessibleProject() {
+        Map<String, String> props = createRequiredProperties(false);
+        props.put(ExternalCatalog.TEST_CONNECTION, "true");
+        TestMaxComputeExternalCatalog catalog = new 
TestMaxComputeExternalCatalog(props);
+        catalog.projectExists = false;
+
+        DdlException exception = Assert.assertThrows(DdlException.class, 
catalog::checkWhenCreating);
+
+        Assert.assertTrue(exception.getMessage().contains("Failed to validate 
MaxCompute project 'mc_project'"));
+        Assert.assertTrue(exception.getMessage().contains("does not exist or 
is not accessible"));
+        Assert.assertNull(catalog.checkedNamespaceSchemaProjectName);
+    }
+
+    @Test
+    public void testCheckWhenCreatingReportsInaccessibleNamespaceSchema() {
+        Map<String, String> props = createRequiredProperties(true);
+        props.put(ExternalCatalog.TEST_CONNECTION, "true");
+        TestMaxComputeExternalCatalog catalog = new 
TestMaxComputeExternalCatalog(props);
+        catalog.threeTierModel = false;
+
+        DdlException exception = Assert.assertThrows(DdlException.class, 
catalog::checkWhenCreating);
+
+        Assert.assertTrue(exception.getMessage().contains("Failed to validate 
MaxCompute project 'mc_project'"));
+        Assert.assertTrue(exception.getMessage().contains("schema list is 
accessible"));
+    }
+
+    private static Map<String, String> createRequiredProperties(boolean 
enableNamespaceSchema) {
+        Map<String, String> props = new HashMap<>();
+        addRequiredProperties(props);
+        props.put(MCProperties.ENABLE_NAMESPACE_SCHEMA, 
Boolean.toString(enableNamespaceSchema));
+        return props;
+    }
+
+    private static void addRequiredProperties(Map<String, String> props) {
+        props.put(MCProperties.PROJECT, "mc_project");
+        props.put(MCProperties.ENDPOINT, 
"http://service.cn-beijing.maxcompute.aliyun-inc.com/api";);
+        props.put(MCProperties.ACCESS_KEY, "access_key");
+        props.put(MCProperties.SECRET_KEY, "secret_key");
+    }
+
+    private static class TestMaxComputeExternalCatalog extends 
MaxComputeExternalCatalog {
+        private boolean projectExists = true;
+        private boolean threeTierModel = true;
+        private String checkedProjectName;
+        private String checkedNamespaceSchemaProjectName;
+
+        private TestMaxComputeExternalCatalog(Map<String, String> props) {
+            super(1L, "mc_catalog", null, props, "");
+        }
+
+        @Override
+        protected boolean maxComputeProjectExists(String projectName) {
+            checkedProjectName = projectName;
+            return projectExists;
+        }
+
+        @Override
+        protected void validateMaxComputeNamespaceSchemaAccess(String 
projectName) {
+            checkedNamespaceSchemaProjectName = projectName;
+            if (!threeTierModel) {
+                throw new RuntimeException("schema list is not accessible");
+            }
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNodeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNodeTest.java
index cd3f30b0f5d..4989c2c53f2 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNodeTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNodeTest.java
@@ -27,6 +27,7 @@ import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.analysis.TupleId;
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.PrimitiveType;
+import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.maxcompute.MaxComputeExternalCatalog;
 import org.apache.doris.datasource.maxcompute.MaxComputeExternalTable;
 import org.apache.doris.datasource.maxcompute.source.MaxComputeSplit.SplitType;
@@ -436,4 +437,27 @@ public class MaxComputeScanNodeTest {
 
         Assert.assertFalse(result.isEmpty());
     }
+
+    @Test
+    public void testGetSplitsRejectsOdpsExternalTable() {
+        assertGetSplitsRejectsUnsupportedOdpsTable(true, false, 
"mc_external_table");
+    }
+
+    @Test
+    public void testGetSplitsRejectsOdpsLogicalView() {
+        assertGetSplitsRejectsUnsupportedOdpsTable(false, true, 
"mc_logical_view");
+    }
+
+    private void assertGetSplitsRejectsUnsupportedOdpsTable(boolean 
isExternalTable, boolean isVirtualView,
+            String tableName) {
+        Mockito.when(odpsTable.isExternalTable()).thenReturn(isExternalTable);
+        Mockito.when(odpsTable.isVirtualView()).thenReturn(isVirtualView);
+        Mockito.when(table.getDbName()).thenReturn("default");
+        Mockito.when(table.getName()).thenReturn(tableName);
+
+        UserException exception = Assert.assertThrows(UserException.class, () 
-> node.getSplits(1));
+        Assert.assertTrue(exception.getMessage().contains(
+                "Reading MaxCompute external table or logical view is not 
supported: default." + tableName));
+        Mockito.verify(odpsTable, Mockito.never()).getFileNum();
+    }
 }
diff --git a/fe/pom.xml b/fe/pom.xml
index 1f7aec359cb..b033f2cfb35 100644
--- a/fe/pom.xml
+++ b/fe/pom.xml
@@ -1426,7 +1426,7 @@ under the License.
                 <version>${maxcompute.version}</version>
             </dependency>
             <dependency>
-                <!-- This is a dependency chain: odps-sdk-core:0.53.2-public → 
credentials-java:0.3.12 → com.aliyun:tea:[1.1.14,2.0.0)-->
+                <!-- Keep tea pinned for Alibaba SDK dependency chains that 
allow com.aliyun:tea:[1.1.14,2.0.0). -->
                 <groupId>com.aliyun</groupId>
                 <artifactId>tea</artifactId>
                 <version>1.4.1</version>
diff --git 
a/regression-test/suites/external_table_p2/maxcompute/test_external_catalog_maxcompute.groovy
 
b/regression-test/suites/external_table_p2/maxcompute/test_external_catalog_maxcompute.groovy
index 6c83b7735d4..9f434da244f 100644
--- 
a/regression-test/suites/external_table_p2/maxcompute/test_external_catalog_maxcompute.groovy
+++ 
b/regression-test/suites/external_table_p2/maxcompute/test_external_catalog_maxcompute.groovy
@@ -341,7 +341,8 @@ suite("test_external_catalog_maxcompute", "p2,external") {
                 "mc.default.project" = "${mc_db}",
                 "mc.access_key" = "${ak}",
                 "mc.secret_key" = "${sk}",
-                "mc.endpoint" = 
"http://service.cn-beijing-vpc.maxcompute.aliyun-inc.com/api";
+                "mc.endpoint" = 
"http://service.cn-beijing-vpc.maxcompute.aliyun-inc.com/api";,
+                "test_connection" = "true"
             );
         """
 
@@ -379,7 +380,8 @@ suite("test_external_catalog_maxcompute", "p2,external") {
                 "mc.default.project" = "${mc_db}",
                 "mc.access_key" = "${ak}",
                 "mc.secret_key" = "${sk}",
-                "mc.endpoint" = 
"http://service.cn-beijing-vpc.maxcompute.aliyun-inc.com/api";
+                "mc.endpoint" = 
"http://service.cn-beijing-vpc.maxcompute.aliyun-inc.com/api";,
+                "test_connection" = "true"
             );
         """
         sql """ switch `${mc_catalog_name}`; """
diff --git 
a/regression-test/suites/external_table_p2/maxcompute/test_max_compute_schema.groovy
 
b/regression-test/suites/external_table_p2/maxcompute/test_max_compute_schema.groovy
index 75d278e9fad..7f8f3bce332 100644
--- 
a/regression-test/suites/external_table_p2/maxcompute/test_max_compute_schema.groovy
+++ 
b/regression-test/suites/external_table_p2/maxcompute/test_max_compute_schema.groovy
@@ -106,7 +106,8 @@ suite("test_max_compute_schema", "p2,external") {
                 "mc.access_key" = "${ak}",
                 "mc.secret_key" = "${sk}",
                 "mc.endpoint" = 
"http://service.cn-beijing-vpc.maxcompute.aliyun-inc.com/api";,
-                "mc.enable.namespace.schema" = "true"
+                "mc.enable.namespace.schema" = "true",
+                "test_connection" = "true"
             );
         """
 
@@ -236,4 +237,4 @@ suite("test_max_compute_schema", "p2,external") {
         qt_mc_join_q34  """SELECT p.product_name, e.department, e.salary FROM 
analytics.product_sales p JOIN iot.employee_salary e ON p.id=e.id ORDER BY 
p.id;"""
         qt_mc_join_q35  """SELECT o.order_id, p.product_name, e.emp_name FROM 
`default`.order_detail o JOIN analytics.product_sales p ON o.id=p.id JOIN 
iot.employee_salary e ON o.id=e.id WHERE o.ds1='202510' ORDER BY o.id;"""
     }
-}
\ No newline at end of file
+}
diff --git 
a/regression-test/suites/external_table_p2/maxcompute/test_max_compute_validate_connection.groovy
 
b/regression-test/suites/external_table_p2/maxcompute/test_max_compute_validate_connection.groovy
new file mode 100644
index 00000000000..d88e65a2340
--- /dev/null
+++ 
b/regression-test/suites/external_table_p2/maxcompute/test_max_compute_validate_connection.groovy
@@ -0,0 +1,102 @@
+// 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.
+
+suite("test_max_compute_validate_connection", "p2,external") {
+    String enabled = context.config.otherConfigs.get("enableMaxComputeTest")
+    if (enabled == null || !enabled.equalsIgnoreCase("true")) {
+        logger.info("disable MaxCompute test.")
+        return
+    }
+
+    String ak = context.config.otherConfigs.get("ak")
+    String sk = context.config.otherConfigs.get("sk")
+    String defaultProject = "mc_datalake"
+    String invalidEndpoint = "http://127.0.0.1:1/api";
+    String catalogDefaultFalse = "test_mc_validate_default_false"
+    String catalogExplicitFalse = "test_mc_validate_explicit_false"
+    String catalogValidateProject = "test_mc_validate_project"
+    String catalogValidateSchema = "test_mc_validate_schema"
+
+    sql """drop catalog if exists ${catalogDefaultFalse}"""
+    sql """drop catalog if exists ${catalogExplicitFalse}"""
+    sql """drop catalog if exists ${catalogValidateProject}"""
+    sql """drop catalog if exists ${catalogValidateSchema}"""
+
+    sql """
+        create catalog ${catalogDefaultFalse} properties (
+            "type" = "max_compute",
+            "mc.default.project" = "${defaultProject}",
+            "mc.access_key" = "${ak}",
+            "mc.secret_key" = "${sk}",
+            "mc.endpoint" = "${invalidEndpoint}",
+            "mc.connect_timeout" = "1",
+            "mc.read_timeout" = "1",
+            "mc.retry_count" = "1"
+        );
+    """
+    sql """drop catalog if exists ${catalogDefaultFalse}"""
+
+    sql """
+        create catalog ${catalogExplicitFalse} properties (
+            "type" = "max_compute",
+            "mc.default.project" = "${defaultProject}",
+            "mc.access_key" = "${ak}",
+            "mc.secret_key" = "${sk}",
+            "mc.endpoint" = "${invalidEndpoint}",
+            "mc.connect_timeout" = "1",
+            "mc.read_timeout" = "1",
+            "mc.retry_count" = "1",
+            "test_connection" = "false"
+        );
+    """
+    sql """drop catalog if exists ${catalogExplicitFalse}"""
+
+    test {
+        sql """
+            create catalog ${catalogValidateProject} properties (
+                "type" = "max_compute",
+                "mc.default.project" = "${defaultProject}",
+                "mc.access_key" = "${ak}",
+                "mc.secret_key" = "${sk}",
+                "mc.endpoint" = "${invalidEndpoint}",
+                "mc.connect_timeout" = "1",
+                "mc.read_timeout" = "1",
+                "mc.retry_count" = "1",
+                "test_connection" = "true"
+            );
+        """
+        exception "Failed to validate MaxCompute project"
+    }
+
+    test {
+        sql """
+            create catalog ${catalogValidateSchema} properties (
+                "type" = "max_compute",
+                "mc.default.project" = "${defaultProject}",
+                "mc.access_key" = "${ak}",
+                "mc.secret_key" = "${sk}",
+                "mc.endpoint" = "${invalidEndpoint}",
+                "mc.connect_timeout" = "1",
+                "mc.read_timeout" = "1",
+                "mc.retry_count" = "1",
+                "mc.enable.namespace.schema" = "true",
+                "test_connection" = "true"
+            );
+        """
+        exception "with namespace schema"
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to