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]