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

shuwenwei pushed a commit to branch sync-generic-changes
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/sync-generic-changes by this 
push:
     new a2a27495db8 [Query] Add the SetColumnProperties execution flow
a2a27495db8 is described below

commit a2a27495db8e4cdf995e64865e3e104dfc488dea
Author: shuwenwei <[email protected]>
AuthorDate: Mon Sep 21 10:58:58 2026 +0800

    [Query] Add the SetColumnProperties execution flow
---
 .../iotdb/db/i18n/DataNodeQueryMessages.java       |   4 +
 .../iotdb/db/i18n/DataNodeQueryMessages.java       |   4 +
 .../iotdb/db/queryengine/plan/Coordinator.java     |   2 +
 .../execution/config/TableConfigTaskVisitor.java   |  69 ++++++++++
 .../config/executor/ClusterConfigTaskExecutor.java |  48 ++++++-
 .../config/executor/IConfigTaskExecutor.java       |   9 ++
 .../AlterTableSetColumnPropertiesTask.java         |  55 ++++++++
 .../plan/relational/sql/ast/AstVisitor.java        |   4 +
 .../sql/ast/DefaultTraversalVisitor.java           |   9 ++
 .../relational/sql/ast/SetColumnProperties.java    | 140 +++++++++++++++++++++
 .../relational/sql/util/DataNodeSqlFormatter.java  |  25 ++++
 .../apache/iotdb/commons/i18n/LBACMessages.java    |   4 +
 .../apache/iotdb/commons/i18n/LBACMessages.java    |   4 +
 .../apache/iotdb/commons/schema/table/TsTable.java |   2 +
 14 files changed, 378 insertions(+), 1 deletion(-)

diff --git 
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
 
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index bf7a3601003..14fe3672d98 100644
--- 
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++ 
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -267,6 +267,10 @@ public final class DataNodeQueryMessages {
       "getPageReader() shouldn't be called here";
   public static final String UNSUPPORTED_COLUMN_TYPE =
       "Unsupported column type: ";
+  public static final String UNSUPPORTED_COLUMN_PROPERTY =
+      "Unsupported column property: ";
+  public static final String 
EXCEPTION_THE_COLUMN_PROPERTY_VALUE_MUST_BE_A_STRING_LITERAL_D6FA0250 =
+      "The column property value must be a string literal.";
   public static final String FAIL_TO_CLOSE_CTEDATAREADER =
       "Fail to close CteDataReader";
   public static final String UNKNOWN_TABLE =
diff --git 
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
 
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index f26f2306be2..24caaa389dc 100644
--- 
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++ 
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -253,6 +253,10 @@ public final class DataNodeQueryMessages {
       "此处不应调用 getPageReader()";
   public static final String UNSUPPORTED_COLUMN_TYPE =
       "不支持的列类型:";
+  public static final String UNSUPPORTED_COLUMN_PROPERTY =
+      "不支持的列属性:";
+  public static final String 
EXCEPTION_THE_COLUMN_PROPERTY_VALUE_MUST_BE_A_STRING_LITERAL_D6FA0250 =
+      "列属性值必须是字符串字面量。";
   public static final String FAIL_TO_CLOSE_CTEDATAREADER =
       "关闭 CteDataReader 失败";
   public static final String UNKNOWN_TABLE =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
index fad2ea1354d..bdc738ddc4b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
@@ -117,6 +117,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RemoveRegion;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameTable;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnComment;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnProperties;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetConfiguration;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetProperties;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetSqlDialect;
@@ -696,6 +697,7 @@ public class Coordinator {
         || statement instanceof AddColumn
         || statement instanceof AlterColumnDataType
         || statement instanceof SetProperties
+        || statement instanceof SetColumnProperties
         || statement instanceof DropColumn
         || statement instanceof DropTable
         || statement instanceof SetTableComment
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index d2f81429d45..2af8eccc173 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -101,6 +101,7 @@ import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableDropColumnTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableRenameColumnTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableRenameTableTask;
+import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableSetColumnPropertiesTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableSetPropertiesTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ClearCacheTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CountDBTask;
@@ -208,6 +209,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RemoveRegion;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameTable;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnComment;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnProperties;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetConfiguration;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetProperties;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetSqlDialect;
@@ -264,6 +266,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.sys.SetSystemStatusStateme
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowConfigurationStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.StartRepairDataStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.StopRepairDataStatement;
+import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
 import org.apache.iotdb.db.subscription.columnfilter.ColumnFilterParser;
 import org.apache.iotdb.pipe.api.customizer.parameter.PipeParameters;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -289,6 +292,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 
+import static com.google.common.util.concurrent.Futures.immediateFuture;
 import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MAX_DATABASE_NAME_LENGTH;
 import static org.apache.iotdb.commons.conf.IoTDBConstant.TTL_INFINITE;
 import static 
org.apache.iotdb.commons.executable.ExecutableManager.getUnTrustedUriErrorMsg;
@@ -845,6 +849,40 @@ public class TableConfigTaskVisitor implements 
AstVisitor<IConfigTask, MPPQueryC
         node.isView());
   }
 
+  @Override
+  public IConfigTask visitSetColumnProperties(
+      final SetColumnProperties node, final MPPQueryContext context) {
+    context.setQueryType(QueryType.OTHER);
+    final Pair<String, String> databaseTablePair = 
splitQualifiedName(node.getTableName());
+    final String database = databaseTablePair.getLeft();
+    final String tableName = databaseTablePair.getRight();
+    final QualifiedObjectName table = new QualifiedObjectName(database, 
tableName);
+
+    accessControl.checkCanAlterTable(context.getSession().getUserName(), 
table, context);
+
+    if (!metadata.tableExists(table)) {
+      if (node.tableIfExists()) {
+        return configTaskExecutor ->
+            immediateFuture(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
+      }
+      if (!DataNodeTableCache.getInstance().isDatabaseExist(database)) {
+        throw new SemanticException(
+            new org.apache.iotdb.commons.exception.IoTDBException(
+                String.format(DataNodeQueryMessages.UNKNOWN_DATABASE, 
database),
+                TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()));
+      }
+    }
+
+    return new AlterTableSetColumnPropertiesTask(
+        database,
+        tableName,
+        node.getColumnName().getValue(),
+        convertColumnPropertiesToMap(node.getProperties(), true),
+        context.getQueryId().getId(),
+        node.tableIfExists(),
+        node.columnIfExists());
+  }
+
   @Override
   public IConfigTask visitSetProperties(final SetProperties node, final 
MPPQueryContext context) {
     context.setQueryType(QueryType.OTHER);
@@ -991,6 +1029,37 @@ public class TableConfigTaskVisitor implements 
AstVisitor<IConfigTask, MPPQueryC
     return map;
   }
 
+  private Map<String, String> convertColumnPropertiesToMap(
+      final List<Property> propertyList, final boolean serializeDefault) {
+    final Map<String, String> map = new HashMap<>();
+    final Set<String> deduplicate = new HashSet<>();
+    for (final Property property : propertyList) {
+      final String key = 
property.getName().getValue().toLowerCase(Locale.ENGLISH);
+      if (!deduplicate.add(key)) {
+        throw new SemanticException(DataNodeQueryMessages.DUPLICATED_PROPERTY 
+ key);
+      }
+      if (!TsTable.COLUMN_ALLOWED_PROPERTIES.contains(key)) {
+        throw new SemanticException(
+            DataNodeQueryMessages.TABLE_PROPERTY
+                + key
+                + DataNodeQueryMessages.IS_CURRENTLY_NOT_ALLOWED);
+      }
+      if (!property.isSetToDefault()) {
+        map.put(
+            key,
+            parseStringFromLiteralIfBinary(property.getNonDefaultValue())
+                .orElseThrow(
+                    () ->
+                        new SemanticException(
+                            DataNodeQueryMessages
+                                
.EXCEPTION_THE_COLUMN_PROPERTY_VALUE_MUST_BE_A_STRING_LITERAL_D6FA0250)));
+      } else if (serializeDefault) {
+        map.put(key, null);
+      }
+    }
+    return map;
+  }
+
   private TSDataType getDataType(final DataType dataType) {
     try {
       return getTSDataType(metadata.getType(toTypeSignature(dataType)));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 7a3580fe66b..e239deb1a14 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -5198,7 +5198,53 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
               client);
 
       if (TSStatusCode.SUCCESS_STATUS.getStatusCode() == tsStatus.getCode()
-          || TSStatusCode.TABLE_NOT_EXISTS.getStatusCode() == 
tsStatus.getCode() && ifExists) {
+          || (TSStatusCode.TABLE_NOT_EXISTS.getStatusCode() == 
tsStatus.getCode() && ifExists)) {
+        future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
+      } else {
+        future.setException(
+            new IoTDBException(getTableErrorMessage(tsStatus, database), 
tsStatus.getCode()));
+      }
+    } catch (final ClientManagerException | TException e) {
+      future.setException(e);
+    }
+    return future;
+  }
+
+  @Override
+  public SettableFuture<ConfigTaskResult> alterTableSetColumnProperties(
+      final String database,
+      final String tableName,
+      final String columnName,
+      final Map<String, String> properties,
+      final String queryId,
+      final boolean tableIfExists,
+      final boolean columnIfExists) {
+    final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+    try (final ConfigNodeClient client =
+        
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+
+      final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+      try {
+        ReadWriteIOUtils.write(columnName, stream);
+        ReadWriteIOUtils.write(properties, stream);
+      } catch (final IOException ignored) {
+        // ByteArrayOutputStream won't throw IOException
+      }
+
+      final TSStatus tsStatus =
+          sendAlterReq2ConfigNode(
+              database,
+              tableName,
+              queryId,
+              AlterOrDropTableOperationType.SET_COLUMN_PROPERTIES,
+              stream.toByteArray(),
+              false,
+              client);
+
+      if (TSStatusCode.SUCCESS_STATUS.getStatusCode() == tsStatus.getCode()
+          || (TSStatusCode.TABLE_NOT_EXISTS.getStatusCode() == 
tsStatus.getCode() && tableIfExists)
+          || (TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode() == 
tsStatus.getCode()
+              && columnIfExists)) {
         future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
       } else {
         future.setException(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
index 964b1c52779..9fd3f7e9d5d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -430,6 +430,15 @@ public interface IConfigTaskExecutor {
       final boolean ifExists,
       final boolean isView);
 
+  SettableFuture<ConfigTaskResult> alterTableSetColumnProperties(
+      final String database,
+      final String tableName,
+      final String columnName,
+      final Map<String, String> properties,
+      final String queryId,
+      final boolean tableIfExists,
+      final boolean columnIfExists);
+
   SettableFuture<ConfigTaskResult> alterTableCommentTable(
       final String database,
       final String tableName,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableSetColumnPropertiesTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableSetColumnPropertiesTask.java
new file mode 100644
index 00000000000..d1265603954
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableSetColumnPropertiesTask.java
@@ -0,0 +1,55 @@
+/*
+ * 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.iotdb.db.queryengine.plan.execution.config.metadata.relational;
+
+import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
+import 
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Map;
+
+public class AlterTableSetColumnPropertiesTask extends 
AbstractAlterOrDropTableTask {
+
+  private final String columnName;
+  private final Map<String, String> properties;
+  private final boolean columnIfExists;
+
+  public AlterTableSetColumnPropertiesTask(
+      final String database,
+      final String tableName,
+      final String columnName,
+      final Map<String, String> properties,
+      final String queryId,
+      final boolean tableIfExists,
+      final boolean columnIfExists) {
+    super(database, tableName, queryId, tableIfExists, false);
+    this.columnName = columnName;
+    this.properties = properties;
+    this.columnIfExists = columnIfExists;
+  }
+
+  @Override
+  public ListenableFuture<ConfigTaskResult> execute(final IConfigTaskExecutor 
configTaskExecutor)
+      throws InterruptedException {
+    return configTaskExecutor.alterTableSetColumnProperties(
+        database, tableName, columnName, properties, queryId, tableIfExists, 
columnIfExists);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
index 86084ff2c6a..9e62a311713 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
@@ -163,6 +163,10 @@ public interface AstVisitor<R, C> extends 
CommonQueryAstVisitor<R, C> {
     return visitStatement(node, context);
   }
 
+  default R visitSetColumnProperties(SetColumnProperties node, C context) {
+    return visitStatement(node, context);
+  }
+
   default R visitRenameColumn(RenameColumn node, C context) {
     return visitStatement(node, context);
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java
index 43cee9d88e7..9b1c48f3799 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java
@@ -515,6 +515,15 @@ public abstract class DefaultTraversalVisitor<C> 
implements AstVisitor<Void, C>
     return null;
   }
 
+  @Override
+  public Void visitSetColumnProperties(final SetColumnProperties node, final C 
context) {
+    for (final Property property : node.getProperties()) {
+      process(property, context);
+    }
+
+    return null;
+  }
+
   @Override
   public Void visitAddColumn(final AddColumn node, final C context) {
     process(node.getColumn(), context);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/SetColumnProperties.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/SetColumnProperties.java
new file mode 100644
index 00000000000..c8391efd591
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/SetColumnProperties.java
@@ -0,0 +1,140 @@
+/*
+ * 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.iotdb.db.queryengine.plan.relational.sql.ast;
+
+import org.apache.iotdb.commons.i18n.LBACMessages;
+import 
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.AstMemoryEstimationHelper;
+import 
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.IAstVisitor;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Identifier;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Node;
+import 
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.NodeLocation;
+import 
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.QualifiedName;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tsfile.utils.RamUsageEstimator;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class SetColumnProperties extends Statement {
+
+  private static final long INSTANCE_SIZE =
+      RamUsageEstimator.shallowSizeOfInstance(SetColumnProperties.class);
+
+  private final QualifiedName tableName;
+  private final Identifier columnName;
+  private final List<Property> properties;
+  private final boolean tableIfExists;
+  private final boolean columnIfExists;
+
+  public SetColumnProperties(
+      final NodeLocation location,
+      final QualifiedName tableName,
+      final Identifier columnName,
+      final List<Property> properties,
+      final boolean tableIfExists,
+      final boolean columnIfExists) {
+    super(requireNonNull(location, 
LBACMessages.EXCEPTION_LOCATION_IS_NULL_399F8D73));
+    this.tableName = requireNonNull(tableName, 
LBACMessages.EXCEPTION_TABLENAME_IS_NULL_6B6687B9);
+    this.columnName =
+        requireNonNull(columnName, 
LBACMessages.EXCEPTION_COLUMNNAME_IS_NULL_46BD2848);
+    this.properties =
+        ImmutableList.copyOf(
+            requireNonNull(properties, 
LBACMessages.EXCEPTION_PROPERTIES_IS_NULL_08E70FBB));
+    this.tableIfExists = tableIfExists;
+    this.columnIfExists = columnIfExists;
+  }
+
+  public QualifiedName getTableName() {
+    return tableName;
+  }
+
+  public Identifier getColumnName() {
+    return columnName;
+  }
+
+  public List<Property> getProperties() {
+    return properties;
+  }
+
+  public boolean tableIfExists() {
+    return tableIfExists;
+  }
+
+  public boolean columnIfExists() {
+    return columnIfExists;
+  }
+
+  @Override
+  public <R, C> R accept(final IAstVisitor<R, C> visitor, final C context) {
+    return ((AstVisitor<R, C>) visitor).visitSetColumnProperties(this, 
context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    final SetColumnProperties that = (SetColumnProperties) o;
+    return tableIfExists == that.tableIfExists
+        && columnIfExists == that.columnIfExists
+        && Objects.equals(tableName, that.tableName)
+        && Objects.equals(columnName, that.columnName)
+        && Objects.equals(properties, that.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(tableName, columnName, properties, tableIfExists, 
columnIfExists);
+  }
+
+  @Override
+  public String toString() {
+    return toStringHelper(this)
+        .add("tableName", tableName)
+        .add("columnName", columnName)
+        .add("properties", properties)
+        .add("tableIfExists", tableIfExists)
+        .add("columnIfExists", columnIfExists)
+        .toString();
+  }
+
+  @Override
+  public long ramBytesUsed() {
+    long size = INSTANCE_SIZE;
+    size += 
AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
+    size += tableName.ramBytesUsed();
+    size += 
AstMemoryEstimationHelper.getEstimatedSizeOfAccountableObject(columnName);
+    size += AstMemoryEstimationHelper.getEstimatedSizeOfNodeList(properties);
+    return size;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
index dec3cc58b96..63e94c23238 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
@@ -60,6 +60,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RelationalAuthorS
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameTable;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnComment;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnProperties;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetProperties;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetTableComment;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowClusterId;
@@ -389,6 +390,30 @@ public final class DataNodeSqlFormatter extends 
CommonQuerySqlFormatter
     return null;
   }
 
+  @Override
+  public Void visitSetColumnProperties(SetColumnProperties node, Integer 
context) {
+    builder.append("ALTER TABLE ");
+    if (node.tableIfExists()) {
+      builder.append("IF EXISTS ");
+    }
+    builder
+        .append(CommonQuerySqlFormatter.formatName(node.getTableName()))
+        .append(" ALTER COLUMN ");
+    if (node.columnIfExists()) {
+      builder.append("IF EXISTS ");
+    }
+    builder.append(CommonQuerySqlFormatter.formatName(node.getColumnName()));
+    for (final Property property : node.getProperties()) {
+      switch (property.getName().getValue()) {
+        // No column property key is supported in this edition.
+        default:
+          throw new UnsupportedOperationException(
+              DataNodeQueryMessages.UNSUPPORTED_COLUMN_PROPERTY + 
property.getName().getValue());
+      }
+    }
+    return null;
+  }
+
   @Override
   public Void visitRenameColumn(RenameColumn node, Integer indent) {
     builder.append("ALTER");
diff --git 
a/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java
 
b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java
index 85453a94678..3a5fb22c677 100644
--- 
a/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java
+++ 
b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java
@@ -25,4 +25,8 @@ public final class LBACMessages {
 
   public static final String 
EXCEPTION_LBAC_CHECK_FAILED_FOR_USER_ARG_ARG_TO_LABEL_ARG_VALUE_ARG_UNDER_POLICY_ARG_USER_S_MERGED_GRANT_ARG_DOES_NOT_DOMINATE_REQUIRED_ARG_C18D4EA7
 = "LBAC check failed for user '%s' %s to label '%s' (value: %s) under policy 
'%s': user's merged grant %s does not dominate required %s";
   public static final String EXCEPTION_LABELNAME_IS_NULL_856ABAE4 = "labelName 
is null";
+  public static final String EXCEPTION_LOCATION_IS_NULL_399F8D73 = "location 
is null";
+  public static final String EXCEPTION_TABLENAME_IS_NULL_6B6687B9 = "tableName 
is null";
+  public static final String EXCEPTION_COLUMNNAME_IS_NULL_46BD2848 = 
"columnName is null";
+  public static final String EXCEPTION_PROPERTIES_IS_NULL_08E70FBB = 
"properties is null";
 }
diff --git 
a/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java
 
b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java
index ce7d66b9f17..935a98d5226 100644
--- 
a/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java
+++ 
b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java
@@ -25,4 +25,8 @@ public final class LBACMessages {
 
   public static final String 
EXCEPTION_LBAC_CHECK_FAILED_FOR_USER_ARG_ARG_TO_LABEL_ARG_VALUE_ARG_UNDER_POLICY_ARG_USER_S_MERGED_GRANT_ARG_DOES_NOT_DOMINATE_REQUIRED_ARG_C18D4EA7
 = "用户 '%s' 的 %s 访问失败:标签 '%s'(值:%s)位于策略 '%s' 下,用户合并后的授权 %s 不支配所需值 %s";
   public static final String EXCEPTION_LABELNAME_IS_NULL_856ABAE4 = "labelName 
为 null";
+  public static final String EXCEPTION_LOCATION_IS_NULL_399F8D73 = "location 为 
null";
+  public static final String EXCEPTION_TABLENAME_IS_NULL_6B6687B9 = "tableName 
为 null";
+  public static final String EXCEPTION_COLUMNNAME_IS_NULL_46BD2848 = 
"columnName 为 null";
+  public static final String EXCEPTION_PROPERTIES_IS_NULL_08E70FBB = 
"properties 为 null";
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
index 14481bfa9bc..681c638bc56 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
@@ -65,6 +65,8 @@ public class TsTable {
   public static final String TIME_COLUMN_NAME = "time";
   public static final String COMMENT_KEY = "__comment";
   public static final String TTL_PROPERTY = "ttl";
+  // No column property key is supported yet.
+  public static final Set<String> COLUMN_ALLOWED_PROPERTIES = 
Collections.emptySet();
   public static final String NEED_LAST_CACHE_PROPERTY = "need_last_cache";
   public static final Set<String> TABLE_ALLOWED_PROPERTIES =
       Collections.unmodifiableSet(

Reply via email to