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

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new f1a40a7dbb [#9754] feat(clickhouse): Add schema operations for 
ClickHouse catalog (#9761)
f1a40a7dbb is described below

commit f1a40a7dbb67b9b328a4f78f580cc88170e29c12
Author: Qi Yu <[email protected]>
AuthorDate: Sat Jan 31 02:45:57 2026 +0800

    [#9754] feat(clickhouse): Add schema operations for ClickHouse catalog 
(#9761)
    
    ### What changes were proposed in this pull request?
    
    This PR adds support for schema operations.
    
    ### Why are the changes needed?
    
    It's a need from the user community.
    
    Fix: #9754
    
    ### Does this PR introduce _any_ user-facing change?
    
    N/A
    
    ### How was this patch tested?
    
    UTs
---
 .github/workflows/build.yml                        |  1 +
 .../catalog/clickhouse/ClickHouseCatalog.java      | 11 ++++
 .../clickhouse/ClickHouseCatalogCapability.java    | 61 +++++++++++++------
 ...va => ClickHouseCatalogPropertiesMetadata.java} | 21 ++++++-
 .../catalog/clickhouse/ClickHouseConfig.java       | 57 ++++++++++++++++++
 ...logCapability.java => ClickHouseConstants.java} | 10 +++-
 .../ClickHouseSchemaPropertiesMetadata.java        | 57 ++++++++++++++++++
 .../converter/ClickHouseExceptionConverter.java    | 30 +++++++++-
 .../operations/ClickHouseDatabaseOperations.java   | 65 +++++++++++++++++++-
 .../TestClickHouseCatalogPropertiesMeta.java}      | 19 ++++--
 .../TestClickHouseSchemaPropertiesMetadata.java    | 45 ++++++++++++++
 .../TestClickHouseDatabaseOperations.java          | 69 ++++++++++++++++++++++
 12 files changed, 414 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index c3408c0824..0032e7ac7e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -25,6 +25,7 @@ jobs:
             source_changes:
               - '.github/**'
               - 'catalogs/**'
+              - 'catalogs-contrib/**'
               - 'clients/**'
               - 'conf/**'
               - 'dev/**'
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalog.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalog.java
index 8d547c2aa0..03d9650d58 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalog.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalog.java
@@ -29,6 +29,7 @@ import 
org.apache.gravitino.catalog.jdbc.converter.JdbcExceptionConverter;
 import org.apache.gravitino.catalog.jdbc.converter.JdbcTypeConverter;
 import org.apache.gravitino.catalog.jdbc.operation.JdbcDatabaseOperations;
 import org.apache.gravitino.catalog.jdbc.operation.JdbcTableOperations;
+import org.apache.gravitino.connector.PropertiesMetadata;
 import org.apache.gravitino.connector.capability.Capability;
 
 public class ClickHouseCatalog extends JdbcCatalog {
@@ -67,4 +68,14 @@ public class ClickHouseCatalog extends JdbcCatalog {
   public Capability newCapability() {
     return new ClickHouseCatalogCapability();
   }
+
+  @Override
+  public PropertiesMetadata catalogPropertiesMetadata() throws 
UnsupportedOperationException {
+    return new ClickHouseCatalogPropertiesMetadata();
+  }
+
+  @Override
+  public PropertiesMetadata schemaPropertiesMetadata() throws 
UnsupportedOperationException {
+    return new ClickHouseSchemaPropertiesMetadata();
+  }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
index 8ce7478945..ad0030b7b6 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
@@ -1,26 +1,51 @@
 /*
- *  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
+ * 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
+ *  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.
+ * 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.gravitino.catalog.clickhouse;
 
-import org.apache.gravitino.catalog.jdbc.JdbcCatalogCapability;
+import org.apache.gravitino.connector.capability.Capability;
+import org.apache.gravitino.connector.capability.CapabilityResult;
+
+public class ClickHouseCatalogCapability implements Capability {
+  /**
+   * Regular expression explanation: ^[\w\p{L}-$/=]{1,64}$
+   *
+   * <p>^ - Start of the string
+   *
+   * <p>[\w\p{L}-$/=]{1,64} - Consist of 1 to 64 characters of letters (both 
cases), digits,
+   * underscores, any kind of letter from any language, hyphens, dollar signs, 
slashes or equal
+   * signs
+   *
+   * <p>\w - matches [a-zA-Z0-9_]
+   *
+   * <p>\p{L} - matches any kind of letter from any language
+   *
+   * <p>$ - End of the string
+   */
+  public static final String CLICKHOUSE_NAME_PATTERN = 
"^[\\w\\p{L}-$/=]{1,64}$";
 
-public class ClickHouseCatalogCapability extends JdbcCatalogCapability {
-  // No additional capabilities for ClickHouse at this time
+  @Override
+  public CapabilityResult specificationOnName(Scope scope, String name) {
+    // TODO(yuqi): Validate the name against reserved words
+    if (!name.matches(CLICKHOUSE_NAME_PATTERN)) {
+      return CapabilityResult.unsupported(
+          String.format("The %s name '%s' is illegal.", scope, name));
+    }
+    return CapabilityResult.SUPPORTED;
+  }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogPropertiesMetadata.java
similarity index 53%
copy from 
catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
copy to 
catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogPropertiesMetadata.java
index 8ce7478945..43a3079ff6 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogPropertiesMetadata.java
@@ -19,8 +19,23 @@
 
 package org.apache.gravitino.catalog.clickhouse;
 
-import org.apache.gravitino.catalog.jdbc.JdbcCatalogCapability;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.apache.gravitino.catalog.jdbc.JdbcCatalogPropertiesMetadata;
+import org.apache.gravitino.connector.PropertyEntry;
 
-public class ClickHouseCatalogCapability extends JdbcCatalogCapability {
-  // No additional capabilities for ClickHouse at this time
+public class ClickHouseCatalogPropertiesMetadata extends 
JdbcCatalogPropertiesMetadata {
+
+  private static final Map<String, PropertyEntry<?>> PROPERTIES_METADATA = 
ImmutableMap.of();
+
+  @Override
+  protected Map<String, PropertyEntry<?>> specificPropertyEntries() {
+    Map<String, PropertyEntry<?>> superMap = super.specificPropertyEntries();
+    ImmutableMap<String, PropertyEntry<?>> result =
+        new ImmutableMap.Builder<String, PropertyEntry<?>>()
+            .putAll(superMap)
+            .putAll(PROPERTIES_METADATA)
+            .build();
+    return result;
+  }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConfig.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConfig.java
new file mode 100644
index 0000000000..83e99fc0ca
--- /dev/null
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConfig.java
@@ -0,0 +1,57 @@
+/*
+ *  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.gravitino.catalog.clickhouse;
+
+import static 
org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.CLUSTER_NAME;
+import static 
org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.CLUSTER_SHARDING_KEY;
+import static 
org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.ON_CLUSTER;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.gravitino.config.ConfigBuilder;
+import org.apache.gravitino.config.ConfigConstants;
+import org.apache.gravitino.config.ConfigEntry;
+
+public class ClickHouseConfig {
+
+  public static final boolean DEFAULT_CK_ON_CLUSTER = false;
+
+  // Constants part
+  public static final ConfigEntry<String> CK_CLUSTER_NAME =
+      new ConfigBuilder(CLUSTER_NAME)
+          .doc("Cluster name for ClickHouse distributed tables")
+          .version(ConfigConstants.VERSION_1_2_0)
+          .stringConf()
+          .checkValue(StringUtils::isNotEmpty, "Cluster name cannot be empty")
+          .create();
+
+  public static final ConfigEntry<Boolean> CK_ON_CLUSTER =
+      new ConfigBuilder(ON_CLUSTER)
+          .doc("Whether to use 'ON CLUSTER' clause when creating tables in 
ClickHouse")
+          .version(ConfigConstants.VERSION_1_2_0)
+          .booleanConf()
+          .createWithDefault(DEFAULT_CK_ON_CLUSTER);
+
+  public static final ConfigEntry<String> CK_CLUSTER_SHARDING_KEY =
+      new ConfigBuilder(CLUSTER_SHARDING_KEY)
+          .doc("Sharding key for ClickHouse distributed tables")
+          .version(ConfigConstants.VERSION_1_2_0)
+          .stringConf()
+          .create();
+}
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java
similarity index 70%
copy from 
catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
copy to 
catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java
index 8ce7478945..fab6db164b 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java
@@ -19,8 +19,12 @@
 
 package org.apache.gravitino.catalog.clickhouse;
 
-import org.apache.gravitino.catalog.jdbc.JdbcCatalogCapability;
+public class ClickHouseConstants {
 
-public class ClickHouseCatalogCapability extends JdbcCatalogCapability {
-  // No additional capabilities for ClickHouse at this time
+  // Name of the clickhouse cluster
+  public static final String CLUSTER_NAME = "cluster-name";
+  // Whether to use 'ON CLUSTER' clause when creating tables
+  public static final String ON_CLUSTER = "on-cluster";
+  // Sharding key for the clickhouse cluster
+  public static final String CLUSTER_SHARDING_KEY = "cluster-sharding-key";
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseSchemaPropertiesMetadata.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseSchemaPropertiesMetadata.java
new file mode 100644
index 0000000000..3ef74118b5
--- /dev/null
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseSchemaPropertiesMetadata.java
@@ -0,0 +1,57 @@
+/*
+ *  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.gravitino.catalog.clickhouse;
+
+import static 
org.apache.gravitino.connector.PropertyEntry.booleanPropertyEntry;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+import org.apache.gravitino.catalog.jdbc.JdbcSchemaPropertiesMetadata;
+import org.apache.gravitino.connector.PropertyEntry;
+
+public class ClickHouseSchemaPropertiesMetadata extends 
JdbcSchemaPropertiesMetadata {
+  private static final Map<String, PropertyEntry<?>> PROPERTIES_METADATA;
+
+  static {
+    List<PropertyEntry<?>> propertyEntries =
+        ImmutableList.of(
+            booleanPropertyEntry(
+                ClickHouseConfig.CK_ON_CLUSTER.getKey(),
+                ClickHouseConfig.CK_ON_CLUSTER.getDoc(),
+                false /* required */,
+                false /* immutable */,
+                false /* defaultValue */,
+                false /* hidden */,
+                false /* reserved */));
+    PROPERTIES_METADATA = Maps.uniqueIndex(propertyEntries, 
PropertyEntry::getName);
+  }
+
+  @Override
+  public Map<String, PropertyEntry<?>> propertyEntries() {
+    Map<String, PropertyEntry<?>> stringPropertyEntryMap = 
super.propertyEntries();
+    return new ImmutableMap.Builder<String, PropertyEntry<?>>()
+        .putAll(stringPropertyEntryMap)
+        .putAll(PROPERTIES_METADATA)
+        .build();
+  }
+}
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/converter/ClickHouseExceptionConverter.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/converter/ClickHouseExceptionConverter.java
index 5da5170dd9..c78ab9cb1c 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/converter/ClickHouseExceptionConverter.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/converter/ClickHouseExceptionConverter.java
@@ -18,8 +18,36 @@
  */
 package org.apache.gravitino.catalog.clickhouse.converter;
 
+import java.sql.SQLException;
 import org.apache.gravitino.catalog.jdbc.converter.JdbcExceptionConverter;
+import org.apache.gravitino.exceptions.GravitinoRuntimeException;
+import org.apache.gravitino.exceptions.NoSuchSchemaException;
+import org.apache.gravitino.exceptions.NoSuchTableException;
+import org.apache.gravitino.exceptions.SchemaAlreadyExistsException;
+import org.apache.gravitino.exceptions.TableAlreadyExistsException;
 
 public class ClickHouseExceptionConverter extends JdbcExceptionConverter {
-  // Implement ClickHouse specific exception conversions if needed
+  static final int ERROR_CODE_UNKNOWN_DATABASE = 81;
+  static final int ERROR_CODE_DATABASE_ALREADY_EXISTS = 82;
+
+  static final int ERROR_CODE_TABLE_ALREADY_EXISTS = 57;
+  static final int ERROR_CODE_TABLE_IS_DROPPED = 218;
+
+  @SuppressWarnings("FormatStringAnnotation")
+  @Override
+  public GravitinoRuntimeException toGravitinoException(SQLException 
sqlException) {
+    int errorCode = sqlException.getErrorCode();
+    switch (errorCode) {
+      case ERROR_CODE_DATABASE_ALREADY_EXISTS:
+        return new SchemaAlreadyExistsException(sqlException, 
sqlException.getMessage());
+      case ERROR_CODE_TABLE_ALREADY_EXISTS:
+        return new TableAlreadyExistsException(sqlException, 
sqlException.getMessage());
+      case ERROR_CODE_UNKNOWN_DATABASE:
+        return new NoSuchSchemaException(sqlException, 
sqlException.getMessage());
+      case ERROR_CODE_TABLE_IS_DROPPED:
+        return new NoSuchTableException(sqlException, 
sqlException.getMessage());
+      default:
+        return new GravitinoRuntimeException(sqlException, 
sqlException.getMessage());
+    }
+  }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseDatabaseOperations.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseDatabaseOperations.java
index bc0569bea7..a3902ba1f6 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseDatabaseOperations.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseDatabaseOperations.java
@@ -18,19 +18,78 @@
  */
 package org.apache.gravitino.catalog.clickhouse.operations;
 
-import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableSet;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.gravitino.StringIdentifier;
 import org.apache.gravitino.catalog.jdbc.operation.JdbcDatabaseOperations;
 
 public class ClickHouseDatabaseOperations extends JdbcDatabaseOperations {
 
+  private static final Set<String> CLICK_HOUSE_SYSTEM_DATABASES =
+      ImmutableSet.of("information_schema", "default", "system", 
"INFORMATION_SCHEMA");
+
+  // TODO: handle ClickHouse cluster properly when creating/dropping 
databases/tables
+  //  use https://github.com/apache/gravitino/issues/9820 to track it.
+
   @Override
   protected boolean supportSchemaComment() {
-    return false;
+    return true;
   }
 
   @Override
   protected Set<String> createSysDatabaseNameSet() {
-    return Sets.newHashSet();
+    return CLICK_HOUSE_SYSTEM_DATABASES;
+  }
+
+  @Override
+  public List<String> listDatabases() {
+    List<String> databaseNames = new ArrayList<>();
+    try (final Connection connection = getConnection()) {
+      // It is possible that other catalogs have been deleted,
+      // causing the following statement to error,
+      // so here we manually set a system catalog
+      connection.setCatalog(createSysDatabaseNameSet().iterator().next());
+      try (Statement statement = connection.createStatement();
+          ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
+        while (resultSet.next()) {
+          String databaseName = resultSet.getString(1);
+          if (!isSystemDatabase(databaseName)) {
+            databaseNames.add(databaseName);
+          }
+        }
+      }
+      return databaseNames;
+    } catch (final SQLException se) {
+      throw this.exceptionMapper.toGravitinoException(se);
+    }
+  }
+
+  @Override
+  protected String generateCreateDatabaseSql(
+      String databaseName, String comment, Map<String, String> properties) {
+
+    String originComment = StringIdentifier.removeIdFromComment(comment);
+    if (!supportSchemaComment() && StringUtils.isNotEmpty(originComment)) {
+      throw new UnsupportedOperationException(
+          "Doesn't support setting schema comment: " + originComment);
+    }
+
+    StringBuilder createDatabaseSql =
+        new StringBuilder(String.format("CREATE DATABASE `%s`", databaseName));
+
+    if (StringUtils.isNotEmpty(originComment)) {
+      createDatabaseSql.append(String.format(" COMMENT '%s'", originComment));
+    }
+
+    LOG.info("Generated create database:{} sql: {}", databaseName, 
createDatabaseSql);
+    return createDatabaseSql.toString();
   }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseCatalogPropertiesMeta.java
similarity index 55%
copy from 
catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
copy to 
catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseCatalogPropertiesMeta.java
index 8ce7478945..6e18407ba1 100644
--- 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseCatalogCapability.java
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseCatalogPropertiesMeta.java
@@ -16,11 +16,22 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.apache.gravitino.catalog.clickhouse;
 
-import org.apache.gravitino.catalog.jdbc.JdbcCatalogCapability;
+import java.util.Map;
+import org.apache.gravitino.catalog.jdbc.config.JdbcConfig;
+import org.apache.gravitino.connector.PropertyEntry;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestClickHouseCatalogPropertiesMeta {
 
-public class ClickHouseCatalogCapability extends JdbcCatalogCapability {
-  // No additional capabilities for ClickHouse at this time
+  @Test
+  void testSpecificPropertyEntriesIncludeClickHouseSettings() {
+    ClickHouseCatalogPropertiesMetadata meta = new 
ClickHouseCatalogPropertiesMetadata();
+    Map<String, PropertyEntry<?>> entries = meta.specificPropertyEntries();
+    // Should still include base JDBC properties
+    Assertions.assertTrue(entries.containsKey(JdbcConfig.JDBC_URL.getKey()));
+    Assertions.assertTrue(entries.containsKey(JdbcConfig.USERNAME.getKey()));
+  }
 }
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseSchemaPropertiesMetadata.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseSchemaPropertiesMetadata.java
new file mode 100644
index 0000000000..f50cb4de9d
--- /dev/null
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/TestClickHouseSchemaPropertiesMetadata.java
@@ -0,0 +1,45 @@
+/*
+ *  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.gravitino.catalog.clickhouse;
+
+import java.util.Map;
+import org.apache.gravitino.StringIdentifier;
+import org.apache.gravitino.connector.PropertyEntry;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestClickHouseSchemaPropertiesMetadata {
+
+  @Test
+  void testSchemaPropertyEntriesIncludeClusterToggle() {
+    ClickHouseSchemaPropertiesMetadata metadata = new 
ClickHouseSchemaPropertiesMetadata();
+    Map<String, PropertyEntry<?>> entries = metadata.propertyEntries();
+
+    Assertions.assertTrue(
+        entries.containsKey(ClickHouseConfig.CK_ON_CLUSTER.getKey()), "on 
cluster missing");
+    PropertyEntry<?> onCluster = 
entries.get(ClickHouseConfig.CK_ON_CLUSTER.getKey());
+    Assertions.assertEquals(Boolean.FALSE, onCluster.getDefaultValue());
+    Assertions.assertFalse(onCluster.isRequired());
+    Assertions.assertFalse(onCluster.isImmutable());
+    Assertions.assertFalse(onCluster.isHidden());
+
+    // Reserved ID property should still exist
+    Assertions.assertTrue(entries.containsKey(StringIdentifier.ID_KEY));
+  }
+}
diff --git 
a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseDatabaseOperations.java
 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseDatabaseOperations.java
new file mode 100644
index 0000000000..b4ee51d703
--- /dev/null
+++ 
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseDatabaseOperations.java
@@ -0,0 +1,69 @@
+/*
+ *  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.gravitino.catalog.clickhouse.operations;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.gravitino.catalog.clickhouse.ClickHouseConfig;
+import org.apache.gravitino.catalog.jdbc.converter.JdbcExceptionConverter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestClickHouseDatabaseOperations {
+
+  private static class TestableClickHouseDatabaseOperations extends 
ClickHouseDatabaseOperations {
+    String buildCreateSql(String databaseName, String comment, Map<String, 
String> properties) {
+      return generateCreateDatabaseSql(databaseName, comment, properties);
+    }
+
+    String buildDropSql(String databaseName, boolean cascade) {
+      return generateDropDatabaseSql(databaseName, cascade);
+    }
+  }
+
+  private TestableClickHouseDatabaseOperations newOps(Map<String, String> 
conf) {
+    TestableClickHouseDatabaseOperations ops = new 
TestableClickHouseDatabaseOperations();
+    ops.initialize(null, new JdbcExceptionConverter(), conf);
+    return ops;
+  }
+
+  @Test
+  void testGenerateCreateDatabaseSqlWithoutCluster() {
+    Map<String, String> conf = new HashMap<>();
+    String sql = newOps(conf).buildCreateSql("db_name", null, 
Collections.emptyMap());
+    Assertions.assertEquals("CREATE DATABASE `db_name`", sql);
+  }
+
+  @Test
+  void testGenerateCreateDatabaseSqlWithClusterNameButDisabled() {
+    Map<String, String> conf = new HashMap<>();
+    conf.put(ClickHouseConfig.CK_CLUSTER_NAME.getKey(), "ck_cluster");
+
+    String sql = newOps(conf).buildCreateSql("db_name", "comment", 
Collections.emptyMap());
+    Assertions.assertEquals("CREATE DATABASE `db_name` COMMENT 'comment'", 
sql);
+  }
+
+  @Test
+  void testGenerateDropDatabaseSqlWithoutCluster() {
+    Map<String, String> conf = new HashMap<>();
+    String sql = newOps(conf).buildDropSql("db_name", true);
+    Assertions.assertEquals("DROP DATABASE `db_name`", sql);
+  }
+}

Reply via email to