You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by sh...@apache.org on 2026/09/18 00:38:53 UTC
(iotdb) branch sync-generic-changes created (now 0bcc2135bb3)
This is an automated email from the ASF dual-hosted git repository.
shuwenwei pushed a change to branch sync-generic-changes
in repository https://gitbox.apache.org/repos/asf/iotdb.git
at 0bcc2135bb3 set table column properties
This branch includes the following new commits:
new dd5dd976980 [Information Schema] Add SPI extension points for information schema
new a9567a07887 [ConfigNode] Inject additional persistence and snapshot processors via ConfigManagerContext
new a3588879571 [RPC] Reserve LBAC status codes
new 29c06fb929c [LBAC] Add LBAC access control abstraction with allow-all default implementation
new b59462d40e0 [Auth] Persist user/role profiles with a versioned extra segment region
new 2ee6391c382 [LBAC] Clarify AllowAllLBACAccessControl javadoc
new 0789228bff2 [Auth] Remove unused Role/User serialize and deserialize
new 2d75ef3747f [Query] Log LBAC access errors at info level
new 3f075d1f81a [ConfigNode] Reserve snapshot file types and column-properties procedure ids
new 0bcc2135bb3 set table column properties
The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(iotdb) 02/10: [ConfigNode] Inject additional persistence and snapshot processors via ConfigManagerContext
Posted by sh...@apache.org.
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
commit a9567a078876eae9005ca246e8b3a69598e18e67
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 14:39:12 2026 +0800
[ConfigNode] Inject additional persistence and snapshot processors via ConfigManagerContext
---
.../iotdb/confignode/manager/ConfigManager.java | 105 ++++++++++++---------
.../persistence/executor/ConfigPlanExecutor.java | 75 +++++++--------
2 files changed, 94 insertions(+), 86 deletions(-)
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index f86681f2bbe..1c41618d90a 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -67,6 +67,7 @@ import org.apache.iotdb.commons.schema.template.Template;
import org.apache.iotdb.commons.schema.tree.AlterTimeSeriesOperationType;
import org.apache.iotdb.commons.schema.ttl.TTLCache;
import org.apache.iotdb.commons.service.metric.MetricService;
+import org.apache.iotdb.commons.snapshot.SnapshotProcessor;
import org.apache.iotdb.commons.subscription.meta.consumer.CommitProgressKeeper;
import org.apache.iotdb.commons.subscription.meta.consumer.SubscriptionProgressSnapshot;
import org.apache.iotdb.commons.utils.AuthUtils;
@@ -377,58 +378,44 @@ public class ConfigManager implements IManager {
public ConfigManager() throws IOException {
// Build the persistence module
- ClusterInfo clusterInfo = new ClusterInfo();
- NodeInfo nodeInfo = new NodeInfo();
- ClusterSchemaInfo clusterSchemaInfo = new ClusterSchemaInfo();
- PartitionInfo partitionInfo = new PartitionInfo();
- AuthorInfo authorInfo = createAuthorInfo();
- ProcedureInfo procedureInfo = new ProcedureInfo(this);
- UDFInfo udfInfo = new UDFInfo();
- TriggerInfo triggerInfo = new TriggerInfo();
- CQInfo cqInfo = new CQInfo();
- ExternalServiceInfo externalServiceInfo = new ExternalServiceInfo();
- this.permissionManager = createPermissionManager(authorInfo);
- PipeInfo pipeInfo = new PipeInfo(userName -> this.permissionManager.login4Pipe(userName, null));
- QuotaInfo quotaInfo = new QuotaInfo();
- TTLInfo ttlInfo = new TTLInfo();
- SubscriptionInfo subscriptionInfo = new SubscriptionInfo();
-
+ ConfigManagerContext context = createConfigManagerContext();
+ context.clusterInfo = new ClusterInfo();
+ context.nodeInfo = new NodeInfo();
+ context.clusterSchemaInfo = new ClusterSchemaInfo();
+ context.partitionInfo = new PartitionInfo();
+ context.authorInfo = createAuthorInfo();
+ context.procedureInfo = new ProcedureInfo(this);
+ context.udfInfo = new UDFInfo();
+ context.triggerInfo = new TriggerInfo();
+ context.cqInfo = new CQInfo();
+ context.externalServiceInfo = new ExternalServiceInfo();
+ this.permissionManager = createPermissionManager(context.authorInfo);
+ context.pipeInfo = new PipeInfo(userName -> this.permissionManager.login4Pipe(userName, null));
+ context.quotaInfo = new QuotaInfo();
+ context.ttlInfo = new TTLInfo();
+ context.subscriptionInfo = new SubscriptionInfo();
+ initAdditionalInfos(context);
// Build state machine and executor
- ConfigPlanExecutor executor =
- new ConfigPlanExecutor(
- clusterInfo,
- nodeInfo,
- clusterSchemaInfo,
- partitionInfo,
- authorInfo,
- procedureInfo,
- udfInfo,
- triggerInfo,
- cqInfo,
- externalServiceInfo,
- pipeInfo,
- subscriptionInfo,
- quotaInfo,
- ttlInfo);
+ ConfigPlanExecutor executor = createConfigPlanExecutor(context);
this.stateMachine = new ConfigRegionStateMachine(this, executor);
// Build the manager module
- this.clusterManager = new ClusterManager(this, clusterInfo);
- setNodeManager(nodeInfo);
+ this.clusterManager = new ClusterManager(this, context.clusterInfo);
+ setNodeManager(context.nodeInfo);
this.clusterSchemaManager =
new ClusterSchemaManager(
this,
- clusterSchemaInfo,
+ context.clusterSchemaInfo,
new ClusterSchemaQuotaStatistics(
COMMON_CONF.getSeriesLimitThreshold(), COMMON_CONF.getDeviceLimitThreshold()));
- this.partitionManager = new PartitionManager(this, partitionInfo);
- this.procedureManager = createProcedureManager(procedureInfo);
+ this.partitionManager = new PartitionManager(this, context.partitionInfo);
+ this.procedureManager = createProcedureManager(context.procedureInfo);
this.externalServiceManager = new ExternalServiceManager(this);
- this.udfManager = new UDFManager(this, udfInfo);
- this.triggerManager = new TriggerManager(this, triggerInfo);
+ this.udfManager = new UDFManager(this, context.udfInfo);
+ this.triggerManager = new TriggerManager(this, context.triggerInfo);
this.cqManager = new CQManager(this);
- this.pipeManager = new PipeManager(this, pipeInfo);
- this.subscriptionManager = new SubscriptionManager(this, subscriptionInfo);
+ this.pipeManager = new PipeManager(this, context.pipeInfo);
+ this.subscriptionManager = new SubscriptionManager(this, context.subscriptionInfo);
this.auditLogger = new CNAuditLogger(this);
// 1. keep PipeManager initialization before LoadManager initialization, because
@@ -438,8 +425,8 @@ public class ConfigManager implements IManager {
setLoadManager();
this.retryFailedTasksThread = new RetryFailedTasksThread(this);
- this.clusterQuotaManager = new ClusterQuotaManager(this, quotaInfo);
- this.ttlManager = new TTLManager(this, ttlInfo);
+ this.clusterQuotaManager = new ClusterQuotaManager(this, context.quotaInfo);
+ this.ttlManager = new TTLManager(this, context.ttlInfo);
}
public void initConsensusManager() throws IOException {
@@ -459,6 +446,16 @@ public class ConfigManager implements IManager {
return new AuthorInfo();
}
+ protected ConfigManagerContext createConfigManagerContext() {
+ return new ConfigManagerContext();
+ }
+
+ protected void initAdditionalInfos(final ConfigManagerContext context) {}
+
+ protected ConfigPlanExecutor createConfigPlanExecutor(final ConfigManagerContext context) {
+ return new ConfigPlanExecutor(context);
+ }
+
protected void setNodeManager(NodeInfo nodeInfo) {
this.nodeManager = new NodeManager(this, nodeInfo);
}
@@ -3468,4 +3465,26 @@ public class ConfigManager implements IManager {
public void setPermissionManager(final PermissionManager permissionManager) {
this.permissionManager = permissionManager;
}
+
+ public static class ConfigManagerContext {
+
+ public ClusterInfo clusterInfo;
+ public NodeInfo nodeInfo;
+ public ClusterSchemaInfo clusterSchemaInfo;
+ public PartitionInfo partitionInfo;
+ public AuthorInfo authorInfo;
+ public ProcedureInfo procedureInfo;
+ public UDFInfo udfInfo;
+ public TriggerInfo triggerInfo;
+ public CQInfo cqInfo;
+ public ExternalServiceInfo externalServiceInfo;
+ public PipeInfo pipeInfo;
+ public SubscriptionInfo subscriptionInfo;
+ public QuotaInfo quotaInfo;
+ public TTLInfo ttlInfo;
+
+ public List<SnapshotProcessor> getAdditionalInfoList() {
+ return Collections.emptyList();
+ }
+ }
}
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
index 772f46baa31..58bf86d6858 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
@@ -156,6 +156,7 @@ import org.apache.iotdb.confignode.consensus.request.write.trigger.UpdateTrigger
import org.apache.iotdb.confignode.consensus.response.partition.SchemaNodeManagementResp;
import org.apache.iotdb.confignode.exception.physical.UnknownPhysicalPlanTypeException;
import org.apache.iotdb.confignode.i18n.ConfigNodeMessages;
+import org.apache.iotdb.confignode.manager.ConfigManager;
import org.apache.iotdb.confignode.manager.externalservice.ExternalServiceInfo;
import org.apache.iotdb.confignode.manager.pipe.agent.PipeConfigNodeAgent;
import org.apache.iotdb.confignode.persistence.ClusterInfo;
@@ -228,65 +229,53 @@ public class ConfigPlanExecutor {
private final TTLInfo ttlInfo;
- public ConfigPlanExecutor(
- ClusterInfo clusterInfo,
- NodeInfo nodeInfo,
- ClusterSchemaInfo clusterSchemaInfo,
- PartitionInfo partitionInfo,
- AuthorInfo authorInfo,
- ProcedureInfo procedureInfo,
- UDFInfo udfInfo,
- TriggerInfo triggerInfo,
- CQInfo cqInfo,
- ExternalServiceInfo externalServiceInfo,
- PipeInfo pipeInfo,
- SubscriptionInfo subscriptionInfo,
- QuotaInfo quotaInfo,
- TTLInfo ttlInfo) {
+ public ConfigPlanExecutor(final ConfigManager.ConfigManagerContext context) {
this.snapshotProcessorList = new ArrayList<>();
- this.clusterInfo = clusterInfo;
- this.snapshotProcessorList.add(clusterInfo);
+ this.clusterInfo = context.clusterInfo;
+ this.snapshotProcessorList.add(context.clusterInfo);
- this.nodeInfo = nodeInfo;
- this.snapshotProcessorList.add(nodeInfo);
+ this.nodeInfo = context.nodeInfo;
+ this.snapshotProcessorList.add(context.nodeInfo);
- this.clusterSchemaInfo = clusterSchemaInfo;
- this.snapshotProcessorList.add(clusterSchemaInfo);
+ this.clusterSchemaInfo = context.clusterSchemaInfo;
+ this.snapshotProcessorList.add(context.clusterSchemaInfo);
- this.partitionInfo = partitionInfo;
- this.snapshotProcessorList.add(partitionInfo);
+ this.partitionInfo = context.partitionInfo;
+ this.snapshotProcessorList.add(context.partitionInfo);
- this.authorInfo = authorInfo;
- this.snapshotProcessorList.add(authorInfo);
+ this.authorInfo = context.authorInfo;
+ this.snapshotProcessorList.add(context.authorInfo);
- this.triggerInfo = triggerInfo;
- this.snapshotProcessorList.add(triggerInfo);
+ this.triggerInfo = context.triggerInfo;
+ this.snapshotProcessorList.add(context.triggerInfo);
- this.udfInfo = udfInfo;
- this.snapshotProcessorList.add(udfInfo);
+ this.udfInfo = context.udfInfo;
+ this.snapshotProcessorList.add(context.udfInfo);
- this.cqInfo = cqInfo;
- this.snapshotProcessorList.add(cqInfo);
+ this.cqInfo = context.cqInfo;
+ this.snapshotProcessorList.add(context.cqInfo);
- this.externalServiceInfo = externalServiceInfo;
- this.snapshotProcessorList.add(externalServiceInfo);
+ this.externalServiceInfo = context.externalServiceInfo;
+ this.snapshotProcessorList.add(context.externalServiceInfo);
- this.pipeInfo = pipeInfo;
- this.snapshotProcessorList.add(pipeInfo);
+ this.pipeInfo = context.pipeInfo;
+ this.snapshotProcessorList.add(context.pipeInfo);
- this.subscriptionInfo = subscriptionInfo;
- this.snapshotProcessorList.add(subscriptionInfo);
+ this.subscriptionInfo = context.subscriptionInfo;
+ this.snapshotProcessorList.add(context.subscriptionInfo);
- this.procedureInfo = procedureInfo;
- this.snapshotProcessorList.add(procedureInfo);
+ this.procedureInfo = context.procedureInfo;
+ this.snapshotProcessorList.add(context.procedureInfo);
- this.quotaInfo = quotaInfo;
- this.snapshotProcessorList.add(quotaInfo);
+ this.quotaInfo = context.quotaInfo;
+ this.snapshotProcessorList.add(context.quotaInfo);
- this.ttlInfo = ttlInfo;
- this.snapshotProcessorList.add(ttlInfo);
+ this.ttlInfo = context.ttlInfo;
+ this.snapshotProcessorList.add(context.ttlInfo);
+
+ this.snapshotProcessorList.addAll(context.getAdditionalInfoList());
this.snapshotProcessorList.add(PipeConfigNodeAgent.runtime().listener());
}
(iotdb) 01/10: [Information Schema] Add SPI extension points for information schema
Posted by sh...@apache.org.
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
commit dd5dd976980941fe86753c3e78c7f451b01cc4cb
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 14:22:38 2026 +0800
[Information Schema] Add SPI extension points for information schema
---
.../InformationSchemaContentSupplierFactory.java | 36 +++++++++----
.../AdditionalInformationSchemaProvider.java | 59 ++++++++++++++++++++++
...dditionalInformationSchemaProviderRegistry.java | 43 ++++++++++++++++
.../DataNodeLocationSupplierFactory.java | 9 ++++
.../commons/schema/table/InformationSchema.java | 38 ++++++++++++++
5 files changed, 175 insertions(+), 10 deletions(-)
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
index d39f9f396a8..f4fb59f7ca7 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
@@ -89,6 +89,8 @@ import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateViewTask;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanGraphPrinter;
import org.apache.iotdb.db.queryengine.plan.relational.function.DataNodeTableBuiltinTableFunction;
+import org.apache.iotdb.db.queryengine.plan.relational.information.AdditionalInformationSchemaProvider;
+import org.apache.iotdb.db.queryengine.plan.relational.information.AdditionalInformationSchemaProviderRegistry;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.InformationSchemaTableScanNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableDiskUsageInformationSchemaTableScanNode;
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
@@ -173,8 +175,17 @@ public class InformationSchemaContentSupplierFactory {
final List<TSDataType> dataTypes,
final UserEntity userEntity,
final InformationSchemaTableScanNode node) {
- String tableName = node.getQualifiedObjectName().getObjectName();
+ final String tableName = node.getQualifiedObjectName().getObjectName();
try {
+ // Try additional providers first
+ for (final AdditionalInformationSchemaProvider provider :
+ AdditionalInformationSchemaProviderRegistry.getProviders()) {
+ final IInformationSchemaContentSupplier supplier =
+ provider.getContentSupplier(tableName, context, dataTypes, userEntity, node);
+ if (supplier != null) {
+ return supplier;
+ }
+ }
switch (tableName) {
case InformationSchema.QUERIES:
return new QueriesSupplier(dataTypes, userEntity);
@@ -384,14 +395,14 @@ public class InformationSchemaContentSupplierFactory {
}
}
- private static class TableSupplier extends TsBlockSupplier {
+ public static class TableSupplier extends TsBlockSupplier {
private final Iterator<Map.Entry<String, List<TTableInfo>>> dbIterator;
private Iterator<TTableInfo> tableInfoIterator = null;
- private TTableInfo currentTable;
- private String dbName;
+ protected TTableInfo currentTable;
+ protected String dbName;
private final UserEntity userEntity;
- private TableSupplier(final List<TSDataType> dataTypes, final UserEntity userEntity)
+ protected TableSupplier(final List<TSDataType> dataTypes, final UserEntity userEntity)
throws Exception {
super(dataTypes);
this.userEntity = userEntity;
@@ -475,7 +486,7 @@ public class InformationSchemaContentSupplierFactory {
}
}
- private static class ColumnSupplier extends TsBlockSupplier {
+ public static class ColumnSupplier extends TsBlockSupplier {
private final Iterator<Map.Entry<String, Map<String, TableColumnDetailInfo>>> dbIterator;
private Iterator<Map.Entry<String, TableColumnDetailInfo>> tableInfoIterator;
private Iterator<TsTableColumnSchema> columnSchemaIterator;
@@ -483,9 +494,10 @@ public class InformationSchemaContentSupplierFactory {
private String tableName;
private Set<String> preDeletedColumns;
private Map<String, Byte> preAlteredColumns;
+ protected TsTableColumnSchema schema;
private final UserEntity userEntity;
- private ColumnSupplier(final List<TSDataType> dataTypes, final UserEntity userEntity)
+ protected ColumnSupplier(final List<TSDataType> dataTypes, final UserEntity userEntity)
throws Exception {
super(dataTypes);
this.userEntity = userEntity;
@@ -522,7 +534,6 @@ public class InformationSchemaContentSupplierFactory {
@Override
protected void constructLine() {
- final TsTableColumnSchema schema = columnSchemaIterator.next();
columnBuilders[0].writeBinary(new Binary(dbName, TSFileConfig.STRING_CHARSET));
columnBuilders[1].writeBinary(new Binary(tableName, TSFileConfig.STRING_CHARSET));
columnBuilders[2].writeBinary(
@@ -546,10 +557,14 @@ public class InformationSchemaContentSupplierFactory {
columnBuilders[6].appendNull();
}
resultBuilder.declarePosition();
+ schema = null;
}
@Override
public boolean hasNext() {
+ if (Objects.nonNull(schema)) {
+ return true;
+ }
while (Objects.isNull(columnSchemaIterator) || !columnSchemaIterator.hasNext()) {
while (Objects.isNull(tableInfoIterator) || !tableInfoIterator.hasNext()) {
if (!dbIterator.hasNext()) {
@@ -576,6 +591,7 @@ public class InformationSchemaContentSupplierFactory {
}
}
}
+ schema = columnSchemaIterator.next();
return true;
}
}
@@ -1660,13 +1676,13 @@ public class InformationSchemaContentSupplierFactory {
}
}
- private abstract static class TsBlockSupplier implements IInformationSchemaContentSupplier {
+ public abstract static class TsBlockSupplier implements IInformationSchemaContentSupplier {
protected final TsBlockBuilder resultBuilder;
protected final ColumnBuilder[] columnBuilders;
protected final AccessControl accessControl = AuthorityChecker.getAccessControl();
- private TsBlockSupplier(final List<TSDataType> dataTypes) {
+ protected TsBlockSupplier(final List<TSDataType> dataTypes) {
this.resultBuilder = new TsBlockBuilder(dataTypes);
this.columnBuilders = resultBuilder.getValueColumnBuilders();
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProvider.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProvider.java
new file mode 100644
index 00000000000..d0874676ca3
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProvider.java
@@ -0,0 +1,59 @@
+/*
+ * 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.information;
+
+import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
+import org.apache.iotdb.commons.audit.UserEntity;
+import org.apache.iotdb.db.queryengine.execution.operator.OperatorContext;
+import org.apache.iotdb.db.queryengine.execution.operator.source.relational.InformationSchemaContentSupplierFactory.IInformationSchemaContentSupplier;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.node.InformationSchemaTableScanNode;
+
+import org.apache.tsfile.enums.TSDataType;
+
+import java.util.List;
+
+/** Provides additional content and execution locations for information schema tables. */
+public interface AdditionalInformationSchemaProvider {
+
+ /**
+ * Returns the content supplier for the table, or {@code null} if the table is not handled.
+ *
+ * @throws Exception if the content supplier cannot be created.
+ */
+ default IInformationSchemaContentSupplier getContentSupplier(
+ final String tableName,
+ final OperatorContext context,
+ final List<TSDataType> dataTypes,
+ final UserEntity userEntity,
+ final InformationSchemaTableScanNode node)
+ throws Exception {
+ return null;
+ }
+
+ /** Returns the execution location for the table, or {@code null} if the table is not handled. */
+ default List<TDataNodeLocation> getTableLocation(final String tableName) {
+ return null;
+ }
+
+ enum InformationSchemaTableLocation {
+ LOCAL_DATA_NODE,
+ ALL_READABLE_DATA_NODES
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProviderRegistry.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProviderRegistry.java
new file mode 100644
index 00000000000..0f3f22136c3
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/information/AdditionalInformationSchemaProviderRegistry.java
@@ -0,0 +1,43 @@
+/*
+ * 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.information;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ServiceLoader;
+
+public class AdditionalInformationSchemaProviderRegistry {
+
+ private static final List<AdditionalInformationSchemaProvider> PROVIDERS = new ArrayList<>();
+
+ static {
+ for (final AdditionalInformationSchemaProvider provider :
+ ServiceLoader.load(AdditionalInformationSchemaProvider.class)) {
+ PROVIDERS.add(provider);
+ }
+ }
+
+ private AdditionalInformationSchemaProviderRegistry() {}
+
+ public static List<AdditionalInformationSchemaProvider> getProviders() {
+ return Collections.unmodifiableList(PROVIDERS);
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/DataNodeLocationSupplierFactory.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/DataNodeLocationSupplierFactory.java
index 629518313e2..b4d8e8d7a43 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/DataNodeLocationSupplierFactory.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/DataNodeLocationSupplierFactory.java
@@ -33,6 +33,8 @@ import org.apache.iotdb.db.protocol.client.ConfigNodeClient;
import org.apache.iotdb.db.protocol.client.ConfigNodeClientManager;
import org.apache.iotdb.db.protocol.client.ConfigNodeInfo;
import org.apache.iotdb.db.queryengine.common.DataNodeEndPoints;
+import org.apache.iotdb.db.queryengine.plan.relational.information.AdditionalInformationSchemaProvider;
+import org.apache.iotdb.db.queryengine.plan.relational.information.AdditionalInformationSchemaProviderRegistry;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.thrift.TException;
@@ -127,6 +129,13 @@ public class DataNodeLocationSupplierFactory {
@Override
public List<TDataNodeLocation> getDataNodeLocations(final String tableName) {
+ for (final AdditionalInformationSchemaProvider provider :
+ AdditionalInformationSchemaProviderRegistry.getProviders()) {
+ final List<TDataNodeLocation> location = provider.getTableLocation(tableName);
+ if (location != null) {
+ return location;
+ }
+ }
switch (tableName) {
case InformationSchema.QUERIES:
case InformationSchema.TABLE_DISK_USAGE:
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/InformationSchema.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/InformationSchema.java
index 462d9da8eab..92f8950a386 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/InformationSchema.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/InformationSchema.java
@@ -32,7 +32,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
public class InformationSchema {
public static final String INFORMATION_DATABASE = "information_schema";
@@ -494,6 +497,41 @@ public class InformationSchema {
tablesThatSupportPushDownLimitOffset.add(TABLE_DISK_USAGE);
}
+ // ==================== SPI extension point ====================
+
+ static {
+ for (final InformationSchemaExtension extension :
+ ServiceLoader.load(InformationSchemaExtension.class)) {
+ extension.registerAdditionalInformationSchemaTables(schemaTables::put);
+ extension.enhanceInformationSchemaTables(schemaTables::get);
+ }
+ }
+
+ /** Extends the information schema by adding new tables or enhancing existing tables. */
+ public interface InformationSchemaExtension {
+
+ /**
+ * Registers extension-specific information schema tables that do not exist in the built-in
+ * schema.
+ *
+ * @param registerFunc accepts the table name and its schema definition
+ */
+ default void registerAdditionalInformationSchemaTables(
+ final BiConsumer<String, TsTable> registerFunc) {
+ // Do nothing by default
+ }
+
+ /**
+ * Enhances built-in information schema tables, for example by adding extension-specific
+ * columns. The provider returns the mutable schema definition of the requested table.
+ *
+ * @param tableProvider returns the schema definition for a built-in table name
+ */
+ default void enhanceInformationSchemaTables(final Function<String, TsTable> tableProvider) {
+ // Do nothing by default
+ }
+ }
+
public static Map<String, TsTable> getSchemaTables() {
return schemaTables;
}
(iotdb) 06/10: [LBAC] Clarify AllowAllLBACAccessControl javadoc
Posted by sh...@apache.org.
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
commit 2ee6391c382d658123e695642ed8ac4e0d18d673
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 15:26:49 2026 +0800
[LBAC] Clarify AllowAllLBACAccessControl javadoc
---
.../main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java
index 49e7c0d30ae..77cbb11b96b 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java
@@ -28,8 +28,8 @@ import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import java.util.Map;
/**
- * Open-source default implementation of {@link ILBACAccessControl} that allows all access. The
- * commercial TimechoDB DataNode replaces this with its real LBAC implementation during startup.
+ * Default implementation of {@link ILBACAccessControl} that allows all access. A DataNode may
+ * replace it with a real LBAC implementation during startup.
*/
@SuppressWarnings("java:S100")
public class AllowAllLBACAccessControl implements ILBACAccessControl {
(iotdb) 04/10: [LBAC] Add LBAC access control abstraction with allow-all default implementation
Posted by sh...@apache.org.
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
commit 29c06fb929ca6de4fdf22d07bb49638938ddaf1d
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 15:04:37 2026 +0800
[LBAC] Add LBAC access control abstraction with allow-all default implementation
---
.../org/apache/iotdb/db/auth/AuthorityChecker.java | 14 ++++
.../iotdb/db/lbac/AllowAllLBACAccessControl.java | 47 ++++++++++++++
.../apache/iotdb/db/lbac/ILBACAccessControl.java | 74 ++++++++++++++++++++++
.../apache/iotdb/commons/i18n/LBACMessages.java | 28 ++++++++
.../apache/iotdb/commons/i18n/LBACMessages.java | 28 ++++++++
.../commons/lbac/LBACAccessDeniedException.java | 56 ++++++++++++++++
.../iotdb/commons/lbac/LBACRuntimeException.java | 33 ++++++++++
.../apache/iotdb/commons/lbac/RequiredLabels.java | 64 +++++++++++++++++++
.../commons/lbac/operation/LabelAccessType.java | 26 ++++++++
9 files changed, 370 insertions(+)
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 0593db10840..9634992f0af 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -41,6 +41,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TTablePrivilege;
import org.apache.iotdb.confignode.rpc.thrift.TUserResp;
import org.apache.iotdb.db.audit.DNAuditLogger;
import org.apache.iotdb.db.i18n.DataNodeMiscMessages;
+import org.apache.iotdb.db.lbac.AllowAllLBACAccessControl;
+import org.apache.iotdb.db.lbac.ILBACAccessControl;
import org.apache.iotdb.db.pipe.source.dataregion.realtime.listener.PipeInsertionDataNodeListener;
import org.apache.iotdb.db.protocol.session.IClientSession;
import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
@@ -109,6 +111,8 @@ public class AuthorityChecker {
private static volatile AccessControl accessControl =
new AccessControlImpl(new ITableAuthCheckerImpl(), new TreeAccessCheckVisitor());
+ private static volatile ILBACAccessControl lbacAccessControl = new AllowAllLBACAccessControl();
+
private AuthorityChecker() {
// empty constructor
}
@@ -122,6 +126,16 @@ public class AuthorityChecker {
AuthorityChecker.accessControl = accessControl;
}
+ @SuppressWarnings("java:S100")
+ public static ILBACAccessControl getLBACAccessControl() {
+ return lbacAccessControl;
+ }
+
+ @SuppressWarnings("java:S100")
+ public static void setLBACAccessControl(final ILBACAccessControl lbacAccessControl) {
+ AuthorityChecker.lbacAccessControl = lbacAccessControl;
+ }
+
public static void setSuperUser(String superUser) {
SUPER_USER = superUser;
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java
new file mode 100644
index 00000000000..49e7c0d30ae
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java
@@ -0,0 +1,47 @@
+/*
+ * 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.lbac;
+
+import org.apache.iotdb.commons.audit.IAuditEntity;
+import org.apache.iotdb.commons.lbac.RequiredLabels;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+import org.apache.iotdb.db.protocol.session.IClientSession;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+
+import java.util.Map;
+
+/**
+ * Open-source default implementation of {@link ILBACAccessControl} that allows all access. The
+ * commercial TimechoDB DataNode replaces this with its real LBAC implementation during startup.
+ */
+@SuppressWarnings("java:S100")
+public class AllowAllLBACAccessControl implements ILBACAccessControl {
+
+ @Override
+ public void checkCanAccess(
+ final Statement statement,
+ final Metadata metadata,
+ final IClientSession clientSession,
+ final IAuditEntity auditEntity) {}
+
+ @Override
+ public void checkCanAccess(
+ final Map<String, RequiredLabels> requiredLabelsByPolicy, final IAuditEntity auditEntity) {}
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java
new file mode 100644
index 00000000000..070118a1ab0
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java
@@ -0,0 +1,74 @@
+/*
+ * 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.lbac;
+
+import org.apache.iotdb.commons.audit.IAuditEntity;
+import org.apache.iotdb.commons.lbac.LBACAccessDeniedException;
+import org.apache.iotdb.commons.lbac.RequiredLabels;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+import org.apache.iotdb.db.protocol.session.IClientSession;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+
+import java.util.Map;
+
+/**
+ * LBAC (Label-Based Access Control) entry point, at the same level as RBAC's {@code AccessControl}.
+ * Performs label-level access checks on protected columns.
+ */
+@SuppressWarnings("java:S100")
+public interface ILBACAccessControl {
+
+ /**
+ * Performs a full LBAC access check for the given DDL statement.
+ *
+ * <p>Internally extracts the required column labels from the statement, loads user/role grants
+ * and LBAC metadata from cache, then compares subject labels against required object labels.
+ *
+ * @param statement the DDL statement to check
+ * @param metadata metadata handle for table schema lookups
+ * @param clientSession the client session for database resolution
+ * @param auditEntity the audit entity carrying the user identity
+ * @throws LBACAccessDeniedException if any required label comparison fails
+ */
+ void checkCanAccess(
+ Statement statement,
+ Metadata metadata,
+ IClientSession clientSession,
+ IAuditEntity auditEntity)
+ throws LBACAccessDeniedException;
+
+ /**
+ * Performs a full LBAC access check for explicitly-declared column label requirements, without
+ * going through the relational StatementAnalyzer (e.g. the tree-model Load TsFile path).
+ *
+ * @param requiredLabelsByPolicy required object labels grouped by policy name
+ * @param auditEntity the audit entity carrying the user identity
+ * @throws LBACAccessDeniedException
+ */
+ void checkCanAccess(Map<String, RequiredLabels> requiredLabelsByPolicy, IAuditEntity auditEntity)
+ throws LBACAccessDeniedException;
+
+ /**
+ * Clears any LBAC-local caches. Invoked when the metadata lease is fenced and the DataNode drops
+ * its caches, so a recovery forces a fresh re-fetch from the ConfigNode. Defaults to a no-op for
+ * implementations without a local cache.
+ */
+ default void clearCache() {}
+}
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
new file mode 100644
index 00000000000..85453a94678
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java
@@ -0,0 +1,28 @@
+/*
+ * 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.commons.i18n;
+
+public final class LBACMessages {
+
+ private 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";
+}
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
new file mode 100644
index 00000000000..ce7d66b9f17
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java
@@ -0,0 +1,28 @@
+/*
+ * 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.commons.i18n;
+
+public final class LBACMessages {
+
+ private 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";
+}
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java
new file mode 100644
index 00000000000..c025e4333fa
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java
@@ -0,0 +1,56 @@
+/*
+ * 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.commons.lbac;
+
+import org.apache.iotdb.commons.audit.IAuditEntity;
+import org.apache.iotdb.commons.i18n.LBACMessages;
+import org.apache.iotdb.commons.lbac.operation.LabelAccessType;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import java.io.Serial;
+import java.util.Set;
+
+/** Thrown when an LBAC label comparison denies access to a protected object. */
+@SuppressWarnings("java:S100")
+public class LBACAccessDeniedException extends LBACRuntimeException {
+
+ @Serial private static final long serialVersionUID = 1L;
+
+ public LBACAccessDeniedException(
+ final IAuditEntity auditEntity,
+ final String policyName,
+ final String subjectValue,
+ final Set<String> objectComponentValues,
+ final String objectLabelName,
+ final LabelAccessType accessType) {
+ super(
+ String.format(
+ LBACMessages
+ .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,
+ auditEntity.getUsername(),
+ accessType,
+ objectLabelName,
+ objectComponentValues,
+ policyName,
+ subjectValue,
+ objectComponentValues),
+ TSStatusCode.LBAC_ACCESS_DENIED);
+ }
+}
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java
new file mode 100644
index 00000000000..04235886f7d
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.commons.lbac;
+
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+@SuppressWarnings("java:S100")
+public class LBACRuntimeException extends IoTDBRuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public LBACRuntimeException(final String message, final TSStatusCode statusCode) {
+ super(message, statusCode.getStatusCode());
+ }
+}
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java
new file mode 100644
index 00000000000..13d63559765
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java
@@ -0,0 +1,64 @@
+/*
+ * 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.commons.lbac;
+
+import org.apache.iotdb.commons.i18n.LBACMessages;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/** The object-side LBAC requirement: protected column labels grouped by READ and WRITE. */
+public final class RequiredLabels {
+
+ private final Set<String> readLabels = new HashSet<>();
+ private final Set<String> writeLabels = new HashSet<>();
+
+ public RequiredLabels requireLabelWithReadAccess(final String labelName) {
+ Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4);
+ readLabels.add(labelName);
+ return this;
+ }
+
+ public RequiredLabels requireLabelWithWriteAccess(final String labelName) {
+ Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4);
+ writeLabels.add(labelName);
+ return this;
+ }
+
+ public RequiredLabels requireLabelWithAllAccess(final String labelName) {
+ Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4);
+ readLabels.add(labelName);
+ writeLabels.add(labelName);
+ return this;
+ }
+
+ public Set<String> getReadLabels() {
+ return readLabels;
+ }
+
+ public Set<String> getWriteLabels() {
+ return writeLabels;
+ }
+
+ public boolean isEmpty() {
+ return readLabels.isEmpty() && writeLabels.isEmpty();
+ }
+}
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java
new file mode 100644
index 00000000000..fd8ce0fdbf6
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java
@@ -0,0 +1,26 @@
+/*
+ * 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.commons.lbac.operation;
+
+public enum LabelAccessType {
+ READ,
+ WRITE,
+ ALL
+}
(iotdb) 05/10: [Auth] Persist user/role profiles with a versioned extra segment region
Posted by sh...@apache.org.
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
commit b59462d40e0cbf67d84e60e9f284847eab096c47
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 15:26:49 2026 +0800
[Auth] Persist user/role profiles with a versioned extra segment region
---
.../schema/CNPhysicalPlanGenerator.java | 33 ++++++++++-
.../commons/auth/role/LocalFileRoleAccessor.java | 69 +++++++++++++++++++++-
.../commons/auth/user/LocalFileUserAccessor.java | 6 +-
3 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
index e4366c45fc4..c2e0e08fe21 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.confignode.persistence.schema;
import org.apache.iotdb.commons.auth.entity.PrivilegeModelType;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
+import org.apache.iotdb.commons.auth.role.LocalFileRoleAccessor.ExtraSegmentType;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.schema.SchemaConstant;
@@ -224,7 +225,7 @@ public class CNPhysicalPlanGenerator
createUser.setPermissions(new HashSet<>());
createUser.setNodeNameList(new ArrayList<>());
planDeque.add(createUser);
- if (tag == 2) {
+ if (tag >= 2) {
final AuthorTreePlan updateUserMaxSession =
new AuthorTreePlan(ConfigPhysicalPlanType.UpdateUserMaxSession);
updateUserMaxSession.setMaxSessionPerUser(dataInputStream.readInt());
@@ -296,6 +297,10 @@ public class CNPhysicalPlanGenerator
}
}
}
+
+ if (tag >= 3) {
+ generateExtraSegmentPhysicalPlans(dataInputStream, user, isUser);
+ }
} catch (IOException ioException) {
logger.error(
ManagerMessages.LOG_GOT_IOEXCEPTION_DESERIALIZE_USE_ROLE_FILE_TYPE_ARG_1B548759,
@@ -307,6 +312,32 @@ public class CNPhysicalPlanGenerator
}
}
+ /**
+ * Reads the extra segment region appended after the RBAC privileges of a user/role profile file.
+ * Each segment is encoded as {@code [type: int32][length: int32][payload: bytes]} and dispatched
+ * by its type. No extra segment types are handled in this branch, so every payload is ignored,
+ * while segments of unknown types written by newer versions stay forward compatible.
+ */
+ private void generateExtraSegmentPhysicalPlans(
+ final DataInputStream dataInputStream, final String granteeName, final boolean isUser)
+ throws IOException {
+ final int extraSegmentCount = dataInputStream.readInt();
+ for (int i = 0; i < extraSegmentCount; i++) {
+ final ExtraSegmentType segmentType = ExtraSegmentType.fromType(dataInputStream.readInt());
+ final int length = dataInputStream.readInt();
+ final byte[] segmentData = new byte[length];
+ dataInputStream.readFully(segmentData);
+ if (segmentType == null) {
+ continue;
+ }
+ switch (segmentType) {
+ default:
+ // No extra segment types are handled in this branch.
+ break;
+ }
+ }
+ }
+
private void generateGrantRolePhysicalPlan() {
try (final DataInputStream roleInputStream =
new DataInputStream(new BufferedInputStream((inputStream)))) {
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/LocalFileRoleAccessor.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/LocalFileRoleAccessor.java
index df7d7f28427..4f57760183d 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/LocalFileRoleAccessor.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/LocalFileRoleAccessor.java
@@ -85,8 +85,34 @@ public class LocalFileRoleAccessor implements IEntityAccessor {
protected final String entityDirPath;
// It might be a good idea to use a Version number to control upgrade compatibility.
- // Now it's version 1
- protected static final int VERSION = 2;
+ // Version 3 appends an extra segment region after the RBAC privileges.
+ protected static final int VERSION = 3;
+
+ /** Types of the extra segments appended after the RBAC privileges in a profile file. */
+ public enum ExtraSegmentType {
+ /** The subject's LBAC label grants and rule exemptions. */
+ LBAC_GRANT_INFO(1);
+
+ private final int type;
+
+ ExtraSegmentType(final int type) {
+ this.type = type;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ /** Returns the segment type matching the given value, or {@code null} if unknown. */
+ public static ExtraSegmentType fromType(final int type) {
+ for (final ExtraSegmentType segmentType : values()) {
+ if (segmentType.type == type) {
+ return segmentType;
+ }
+ }
+ return null;
+ }
+ }
/**
* Reused buffer for primitive types encoding/decoding, which aim to reduce memory fragments. Use
@@ -151,6 +177,38 @@ public class LocalFileRoleAccessor implements IEntityAccessor {
role.setObjectPrivilegeMap(objectPrivilegeMap);
}
+ /**
+ * Writes the extra segment region appended after the RBAC privileges. The region starts with the
+ * segment count. No extra segments are written by this branch, so the region is empty.
+ */
+ protected void saveExtraSegments(BufferedOutputStream outputStream, Role role)
+ throws IOException {
+ IOUtils.writeInt(outputStream, 0, encodingBufferLocal);
+ }
+
+ /**
+ * Reads the extra segment region appended after the RBAC privileges. Each segment is encoded as
+ * [type: int32][length: int32][payload: bytes]. This branch handles no segment type, so every
+ * payload is ignored while profile files written by newer versions can still be loaded.
+ */
+ protected void loadExtraSegments(DataInputStream dataInputStream, Role role) throws IOException {
+ final int extraSegmentCount = dataInputStream.readInt();
+ for (int i = 0; i < extraSegmentCount; i++) {
+ final ExtraSegmentType segmentType = ExtraSegmentType.fromType(dataInputStream.readInt());
+ final int length = dataInputStream.readInt();
+ final byte[] segmentData = new byte[length];
+ dataInputStream.readFully(segmentData);
+ if (segmentType == null) {
+ continue;
+ }
+ switch (segmentType) {
+ default:
+ // No extra segment types are handled in this branch.
+ break;
+ }
+ }
+ }
+
protected void saveSessionPerUser(BufferedOutputStream outputStream, Role role)
throws IOException {
// Just used in LocalFileUserAccessor.java.
@@ -218,10 +276,14 @@ public class LocalFileRoleAccessor implements IEntityAccessor {
loadPrivileges(dataInputStream, role);
return role;
} else {
- assert tag == VERSION;
+ // tag >= 2: version 2 and version 3 share the same leading layout; version 3 additionally
+ // appends the extra segment region.
entityName = IOUtils.readString(dataInputStream, STRING_ENCODING, strBufferLocal);
Role role = new Role(entityName);
loadPrivileges(dataInputStream, role);
+ if (tag >= 3) {
+ loadExtraSegments(dataInputStream, role);
+ }
return role;
}
@@ -276,6 +338,7 @@ public class LocalFileRoleAccessor implements IEntityAccessor {
saveEntityName(outputStream, entity);
saveSessionPerUser(outputStream, entity);
savePrivileges(outputStream, entity);
+ saveExtraSegments(outputStream, entity);
outputStream.flush();
fileOutputStream.getFD().sync();
} catch (Exception e) {
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java
index 5ad0d08fc42..bac866a5291 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java
@@ -172,13 +172,17 @@ public class LocalFileUserAccessor extends LocalFileRoleAccessor {
user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, strBufferLocal));
loadPrivileges(dataInputStream, user);
} else {
- assert (tag == VERSION);
+ // tag >= 2: version 2 and version 3 share the same leading layout; version 3 additionally
+ // appends the extra segment region.
user.setUserId(dataInputStream.readLong());
user.setName(IOUtils.readString(dataInputStream, STRING_ENCODING, strBufferLocal));
user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, strBufferLocal));
user.setMaxSessionPerUser(dataInputStream.readInt());
user.setMinSessionPerUser(dataInputStream.readInt());
loadPrivileges(dataInputStream, user);
+ if (tag >= 3) {
+ loadExtraSegments(dataInputStream, user);
+ }
}
File roleOfUser = checkFileAvailable(entityName, "_role");
(iotdb) 09/10: [ConfigNode] Reserve snapshot file types and column-properties procedure ids
Posted by sh...@apache.org.
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
commit 3f075d1f81a6eeccab6c12cd899c5b3c2d972ffb
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 16:09:06 2026 +0800
[ConfigNode] Reserve snapshot file types and column-properties procedure ids
---
.../iotdb/confignode/persistence/schema/CNSnapshotFileType.java | 4 +++-
.../org/apache/iotdb/confignode/procedure/store/ProcedureType.java | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
index ddace413b6c..3fbfde5e337 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
@@ -28,7 +28,9 @@ public enum CNSnapshotFileType {
ROLE((byte) 2),
USER_ROLE((byte) 3),
SCHEMA((byte) 4),
- TTL((byte) 5);
+ TTL((byte) 5),
+ LBAC_COMPONENT((byte) 6),
+ LBAC_POLICY((byte) 7);
private static final Map<Byte, CNSnapshotFileType> TYPE_SNAPSHOT_MAP = new HashMap<>();
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
index 75299638b60..7514d06bce4 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
@@ -86,6 +86,7 @@ public enum ProcedureType {
RENAME_VIEW_PROCEDURE((short) 764),
ALTER_TABLE_COLUMN_DATATYPE_PROCEDURE((short) 765),
+ SET_TABLE_COLUMN_PROPERTIES_PROCEDURE((short) 767),
/** AI Model */
@Deprecated // Since 2.0.6, all models are managed by AINode
@@ -148,6 +149,7 @@ public enum ProcedureType {
PIPE_ENRICHED_CREATE_TABLE_VIEW_PROCEDURE((short) 1420),
PIPE_ENRICHED_ADD_VIEW_COLUMN_PROCEDURE((short) 1421),
PIPE_ENRICHED_ALTER_COLUMN_DATATYPE_PROCEDURE((short) 1422),
+ PIPE_ENRICHED_SET_TABLE_COLUMN_PROPERTIES_PROCEDURE((short) 1424),
PIPE_ENRICHED_DROP_VIEW_COLUMN_PROCEDURE((short) 143),
PIPE_ENRICHED_DROP_VIEW_PROCEDURE((short) 144),
PIPE_ENRICHED_SET_VIEW_PROPERTIES_PROCEDURE((short) 145),
(iotdb) 07/10: [Auth] Remove unused Role/User serialize and deserialize
Posted by sh...@apache.org.
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
commit 0789228bff2796719a198541dbab78976a42c1da
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 16:03:14 2026 +0800
[Auth] Remove unused Role/User serialize and deserialize
---
.../org/apache/iotdb/db/auth/entity/RoleTest.java | 84 ----------------------
.../org/apache/iotdb/db/auth/entity/UserTest.java | 53 --------------
.../org/apache/iotdb/commons/auth/entity/Role.java | 64 -----------------
.../org/apache/iotdb/commons/auth/entity/User.java | 64 -----------------
4 files changed, 265 deletions(-)
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java
deleted file mode 100644
index 270dd8af689..00000000000
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.auth.entity;
-
-import org.apache.iotdb.commons.auth.entity.DatabasePrivilege;
-import org.apache.iotdb.commons.auth.entity.PathPrivilege;
-import org.apache.iotdb.commons.auth.entity.PrivilegeType;
-import org.apache.iotdb.commons.auth.entity.Role;
-import org.apache.iotdb.commons.auth.entity.TablePrivilege;
-import org.apache.iotdb.commons.conf.IoTDBConstant;
-import org.apache.iotdb.commons.exception.IllegalPathException;
-import org.apache.iotdb.commons.path.PartialPath;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Collections;
-
-public class RoleTest {
-
- @Test
- public void testRole_InitAndSerialize() throws IllegalPathException {
- Role role = new Role("role");
- PathPrivilege pathPrivilege = new PathPrivilege(new PartialPath("root.ln"));
- role.setPrivilegeList(Collections.singletonList(pathPrivilege));
- role.grantPathPrivilege(new PartialPath("root.ln"), PrivilegeType.READ_SCHEMA, true);
- role.grantPathPrivilege(new PartialPath("root.ln"), PrivilegeType.READ_DATA, false);
-
- Assert.assertEquals(
- "Role{name='role', pathPrivilegeList=[root.ln : "
- + "READ_DATA READ_SCHEMA_with_grant_option], systemPrivilegeSet=[], "
- + "AnyScopePrivilegeMap=[], objectPrivilegeSet={}}",
- role.toString());
- Role role1 = new Role("role1");
- role1.deserialize(role.serialize());
- Assert.assertEquals(
- "Role{name='role', pathPrivilegeList=[root.ln : "
- + "READ_DATA READ_SCHEMA_with_grant_option], systemPrivilegeSet=[], "
- + "AnyScopePrivilegeMap=[], objectPrivilegeSet={}}",
- role1.toString());
-
- Role admin = new Role("root");
- PartialPath rootPath = new PartialPath(IoTDBConstant.PATH_ROOT + ".**");
- PathPrivilege pathPri = new PathPrivilege(rootPath);
- DatabasePrivilege databasePrivilege = new DatabasePrivilege("testDB");
- TablePrivilege tablePrivilege = new TablePrivilege("testTable");
- databasePrivilege.getTablePrivilegeMap().put("testTable", tablePrivilege);
- for (PrivilegeType item : PrivilegeType.values()) {
- if (item.isSystemPrivilege()) {
- admin.getSysPrivilege().add(item);
- admin.getSysPriGrantOpt().add(item);
- } else if (item.isPathPrivilege()) {
- pathPri.grantPrivilege(item, true);
- } else if (item.isRelationalPrivilege()) {
- databasePrivilege.grantDBPrivilege(item);
- databasePrivilege.grantDBGrantOption(item);
- databasePrivilege.grantTablePrivilege("testTable", item);
- databasePrivilege.grantTableGrantOption("testTable", item);
- admin.grantAnyScopePrivilege(item, true);
- }
- }
- admin.getDBScopePrivilegeMap().put("testDB", databasePrivilege);
- admin.getPathPrivilegeList().add(pathPri);
- Assert.assertEquals(
- "Role{name='root', pathPrivilegeList=[root.** : READ_DATA_with_grant_option WRITE_DATA_with_grant_option READ_SCHEMA_with_grant_option WRITE_SCHEMA_with_grant_option], systemPrivilegeSet=[USE_MODEL_with_grant_option, MAINTAIN_with_grant_option, EXTEND_TEMPLATE_with_grant_option, SYSTEM_with_grant_option, MANAGE_DATABASE_with_grant_option, MANAGE_USER_with_grant_option, USE_TRIGGER_with_grant_option, USE_CQ_with_grant_option, SECURITY_with_grant_option, USE_PIPE_with_grant_option, [...]
- admin.toString());
- }
-}
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/UserTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/UserTest.java
deleted file mode 100644
index 82e7d8f15b1..00000000000
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/UserTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.auth.entity;
-
-import org.apache.iotdb.commons.auth.entity.PathPrivilege;
-import org.apache.iotdb.commons.auth.entity.PrivilegeType;
-import org.apache.iotdb.commons.auth.entity.User;
-import org.apache.iotdb.commons.exception.IllegalPathException;
-import org.apache.iotdb.commons.path.PartialPath;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Collections;
-
-public class UserTest {
-
- @Test
- public void testUser() throws IllegalPathException {
- User user = new User("user", "password123456");
- PathPrivilege pathPrivilege = new PathPrivilege(new PartialPath("root.ln"));
- user.setPrivilegeList(Collections.singletonList(pathPrivilege));
- user.setPathPrivileges(
- new PartialPath("root.ln"), Collections.singleton(PrivilegeType.WRITE_DATA));
- Assert.assertEquals(
- "User{id=-1, name='user', pathPrivilegeList=[root.ln : WRITE_DATA], "
- + "sysPrivilegeSet=[], AnyScopePrivilegeMap=[], objectPrivilegeMap={}, roleList=[], isOpenIdUser=false}",
- user.toString());
- User user1 = new User("user1", "password1");
- user1.deserialize(user.serialize());
- Assert.assertEquals(
- "User{id=-1, name='user', pathPrivilegeList=[root.ln : WRITE_DATA], "
- + "sysPrivilegeSet=[], AnyScopePrivilegeMap=[], objectPrivilegeMap={}, roleList=[], isOpenIdUser=false}",
- user1.toString());
- Assert.assertEquals(user1, user);
- }
-}
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
index e5296dca60c..4c1a4baa78f 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
@@ -21,17 +21,12 @@ package org.apache.iotdb.commons.auth.entity;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.AuthUtils;
-import org.apache.iotdb.commons.utils.SerializeUtils;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.confignode.rpc.thrift.TDBPrivilege;
import org.apache.iotdb.confignode.rpc.thrift.TPathPrivilege;
import org.apache.iotdb.confignode.rpc.thrift.TRoleResp;
import org.apache.iotdb.confignode.rpc.thrift.TTablePrivilege;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -621,65 +616,6 @@ public class Role {
objectPrivilegeMap);
}
- public ByteBuffer serialize() {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
-
- SerializeUtils.serialize(name, dataOutputStream);
-
- try {
- SerializeUtils.serializePrivilegeTypeSet(sysPrivilegeSet, dataOutputStream);
- SerializeUtils.serializePrivilegeTypeSet(sysPriGrantOpt, dataOutputStream);
- dataOutputStream.writeInt(pathPrivilegeList.size());
- for (PathPrivilege pathPrivilege : pathPrivilegeList) {
- dataOutputStream.write(pathPrivilege.serialize().array());
- }
- SerializeUtils.serializePrivilegeTypeSet(anyScopePrivilegeSet, dataOutputStream);
- SerializeUtils.serializePrivilegeTypeSet(anyScopePrivilegeGrantOptSet, dataOutputStream);
- dataOutputStream.writeInt(objectPrivilegeMap.size());
- for (Map.Entry<String, DatabasePrivilege> item : objectPrivilegeMap.entrySet()) {
- SerializeUtils.serialize(item.getKey(), dataOutputStream);
- dataOutputStream.write(item.getValue().serialize().array());
- }
- } catch (IOException e) {
- // unreachable
- }
-
- return ByteBuffer.wrap(byteArrayOutputStream.toByteArray());
- }
-
- public void deserialize(ByteBuffer buffer) {
- name = SerializeUtils.deserializeString(buffer);
- int sysPrivilegeSize = buffer.getInt();
- sysPrivilegeSet = new HashSet<>();
- for (int i = 0; i < sysPrivilegeSize; i++) {
- sysPrivilegeSet.add(PrivilegeType.values()[buffer.getInt()]);
- }
- int sysPriGrantOptSize = buffer.getInt();
- sysPriGrantOpt = new HashSet<>();
- for (int i = 0; i < sysPriGrantOptSize; i++) {
- sysPriGrantOpt.add(PrivilegeType.values()[buffer.getInt()]);
- }
- int privilegeListSize = buffer.getInt();
- pathPrivilegeList = new ArrayList<>(privilegeListSize);
- for (int i = 0; i < privilegeListSize; i++) {
- PathPrivilege pathPrivilege = new PathPrivilege();
- pathPrivilege.deserialize(buffer);
- pathPrivilegeList.add(pathPrivilege);
- }
-
- SerializeUtils.deserializePrivilegeTypeSet(anyScopePrivilegeSet, buffer);
- SerializeUtils.deserializePrivilegeTypeSet(anyScopePrivilegeGrantOptSet, buffer);
-
- int objectPrivilegesSize = buffer.getInt();
- for (int i = 0; i < objectPrivilegesSize; i++) {
- DatabasePrivilege databasePrivilege = new DatabasePrivilege();
- String objectName = SerializeUtils.deserializeString(buffer);
- databasePrivilege.deserialize(buffer);
- this.objectPrivilegeMap.put(objectName, databasePrivilege);
- }
- }
-
@Override
public String toString() {
return "Role{"
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
index 0bebeaf8e06..16575e505eb 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
@@ -18,18 +18,11 @@
*/
package org.apache.iotdb.commons.auth.entity;
-import org.apache.iotdb.commons.utils.SerializeUtils;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.confignode.rpc.thrift.TListUserInfo;
import org.apache.iotdb.confignode.rpc.thrift.TUserResp;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -187,63 +180,6 @@ public class User extends Role {
isOpenIdUser);
}
- @Override
- public ByteBuffer serialize() {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
-
- SerializeUtils.serialize(super.getName(), dataOutputStream);
- SerializeUtils.serialize(password, dataOutputStream);
-
- try {
- dataOutputStream.writeInt(super.getSysPrivilege().size());
- for (PrivilegeType item : super.getSysPrivilege()) {
- dataOutputStream.writeInt(item.ordinal());
- }
- dataOutputStream.writeInt(super.getSysPriGrantOpt().size());
- for (PrivilegeType item : super.getSysPriGrantOpt()) {
- dataOutputStream.writeInt(item.ordinal());
- }
- dataOutputStream.writeInt(super.getPathPrivilegeList().size());
- for (PathPrivilege pathPrivilege : super.getPathPrivilegeList()) {
- dataOutputStream.write(pathPrivilege.serialize().array());
- }
- } catch (IOException e) {
- // unreachable
- }
- SerializeUtils.serializeStringList(new ArrayList<>(roleSet), dataOutputStream);
-
- return ByteBuffer.wrap(byteArrayOutputStream.toByteArray());
- }
-
- @Override
- public void deserialize(ByteBuffer buffer) {
- super.setName(SerializeUtils.deserializeString(buffer));
- password = SerializeUtils.deserializeString(buffer);
- int systemPriSize = buffer.getInt();
- Set<PrivilegeType> sysPri = new HashSet<>();
- for (int i = 0; i < systemPriSize; i++) {
- sysPri.add(PrivilegeType.values()[buffer.getInt()]);
- }
- super.setSysPrivilegeSet(sysPri);
- int sysPriGrantOptSize = buffer.getInt();
- Set<PrivilegeType> grantOpt = new HashSet<>();
- for (int i = 0; i < sysPriGrantOptSize; i++) {
- grantOpt.add(PrivilegeType.values()[buffer.getInt()]);
- }
- super.setSysPriGrantOpt(grantOpt);
-
- int privilegeListSize = buffer.getInt();
- List<PathPrivilege> privilegeList = new ArrayList<>(privilegeListSize);
- for (int i = 0; i < privilegeListSize; i++) {
- PathPrivilege pathPrivilege = new PathPrivilege();
- pathPrivilege.deserialize(buffer);
- privilegeList.add(pathPrivilege);
- }
- super.setPrivilegeList(privilegeList);
- roleSet = new HashSet<>(SerializeUtils.deserializeStringList(buffer));
- }
-
/**
* TestOnly, get the string representation of the user.
*
(iotdb) 10/10: set table column properties
Posted by sh...@apache.org.
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
commit 0bcc2135bb3715e509db431eb05c852f6f4417f8
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Fri Sep 18 08:38:08 2026 +0800
set table column properties
---
.../consensus/request/ConfigPhysicalPlan.java | 4 +
.../consensus/request/ConfigPhysicalPlanType.java | 1 +
.../request/ConfigPhysicalPlanVisitor.java | 8 +
.../write/table/SetTableColumnPropertiesPlan.java | 80 ++++++++
.../iotdb/confignode/manager/ConfigManager.java | 2 +
.../iotdb/confignode/manager/ProcedureManager.java | 21 ++
.../receiver/protocol/IoTDBConfigNodeReceiver.java | 19 ++
.../PipeConfigPhysicalPlanTSStatusVisitor.java | 7 +
.../pipe/source/ConfigRegionListeningFilter.java | 2 +
.../manager/schema/ClusterSchemaManager.java | 55 ++++++
.../persistence/executor/ConfigPlanExecutor.java | 4 +
.../persistence/schema/ClusterSchemaInfo.java | 11 ++
.../confignode/persistence/schema/ConfigMTree.java | 22 +++
...re.java => AbstractSetPropertiesProcedure.java} | 71 +++----
.../table/SetTableColumnPropertiesProcedure.java | 107 ++++++++++
.../schema/table/SetTablePropertiesProcedure.java | 218 ++-------------------
.../procedure/store/ProcedureFactory.java | 9 +
.../table/AlterOrDropTableOperationType.java | 5 +-
18 files changed, 398 insertions(+), 248 deletions(-)
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
index 0d9ca912571..c70b8c12fcf 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
@@ -118,6 +118,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackCreateTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackPreDeleteTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.AddTableViewColumnPlan;
@@ -430,6 +431,9 @@ public abstract class ConfigPhysicalPlan implements IConsensusRequest {
case SetTableProperties:
plan = new SetTablePropertiesPlan(configPhysicalPlanType);
break;
+ case SetTableColumnProperties:
+ plan = new SetTableColumnPropertiesPlan(configPhysicalPlanType);
+ break;
case SetViewProperties:
plan = new SetViewPropertiesPlan();
break;
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
index 1be95181414..dbc6988ba87 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
@@ -233,6 +233,7 @@ public enum ConfigPhysicalPlanType {
AlterColumnDataType((short) 878),
PreAlterColumnDataType((short) 879),
RollbackPreDeleteTable((short) 880),
+ SetTableColumnProperties((short) 881),
/** Deprecated types for sync, restored them for upgrade. */
@Deprecated
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
index 53e3c4cd37d..283aee3ae58 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
@@ -39,6 +39,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.CommitDeleteTab
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTableColumnPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.AddTableViewColumnPlan;
@@ -174,6 +175,8 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitAddTableViewColumn((AddTableViewColumnPlan) plan, context);
case SetTableProperties:
return visitSetTableProperties((SetTablePropertiesPlan) plan, context);
+ case SetTableColumnProperties:
+ return visitSetTableColumnProperties((SetTableColumnPropertiesPlan) plan, context);
case SetViewProperties:
return visitSetViewProperties((SetViewPropertiesPlan) plan, context);
case RenameTableColumn:
@@ -462,6 +465,11 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitPlan(setTablePropertiesPlan, context);
}
+ public R visitSetTableColumnProperties(
+ final SetTableColumnPropertiesPlan setTableColumnPropertiesPlan, final C context) {
+ return visitPlan(setTableColumnPropertiesPlan, context);
+ }
+
// Use set table properties by default
public R visitSetViewProperties(
final SetViewPropertiesPlan setViewPropertiesPlan, final C context) {
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/table/SetTableColumnPropertiesPlan.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/table/SetTableColumnPropertiesPlan.java
new file mode 100644
index 00000000000..89b18cafc84
--- /dev/null
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/table/SetTableColumnPropertiesPlan.java
@@ -0,0 +1,80 @@
+/*
+ * 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.confignode.consensus.request.write.table;
+
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+public class SetTableColumnPropertiesPlan extends AbstractTablePlan {
+
+ private String columnName;
+ private Map<String, String> properties;
+ private boolean isRollback;
+
+ public SetTableColumnPropertiesPlan(final ConfigPhysicalPlanType type) {
+ super(type);
+ }
+
+ public SetTableColumnPropertiesPlan(
+ final String database,
+ final String tableName,
+ final String columnName,
+ final Map<String, String> properties,
+ final boolean isRollback) {
+ super(ConfigPhysicalPlanType.SetTableColumnProperties, database, tableName);
+ this.columnName = columnName;
+ this.properties = properties;
+ this.isRollback = isRollback;
+ }
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ public boolean isRollback() {
+ return isRollback;
+ }
+
+ @Override
+ protected void serializeImpl(final DataOutputStream stream) throws IOException {
+ super.serializeImpl(stream);
+ ReadWriteIOUtils.write(columnName, stream);
+ ReadWriteIOUtils.write(properties, stream);
+ ReadWriteIOUtils.write(isRollback, stream);
+ }
+
+ @Override
+ protected void deserializeImpl(final ByteBuffer buffer) throws IOException {
+ super.deserializeImpl(buffer);
+ this.columnName = ReadWriteIOUtils.readString(buffer);
+ this.properties = ReadWriteIOUtils.readMap(buffer);
+ this.isRollback = ReadWriteIOUtils.readBool(buffer);
+ }
+}
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index 1c41618d90a..9b5e80a3e86 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -3314,6 +3314,8 @@ public class ConfigManager implements IManager {
return procedureManager.alterTableAddColumn(req);
case SET_PROPERTIES:
return procedureManager.alterTableSetProperties(req);
+ case SET_COLUMN_PROPERTIES:
+ return procedureManager.alterTableSetColumnProperties(req);
case RENAME_COLUMN:
return procedureManager.alterTableRenameColumn(req);
case DROP_COLUMN:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
index 50b003d0494..056c756f683 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
@@ -113,6 +113,7 @@ import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableColumnPr
import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableProcedure;
+import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTableColumnPropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTablePropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.AddViewColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.CreateTableViewProcedure;
@@ -2401,6 +2402,25 @@ public class ProcedureManager {
false));
}
+ public TSStatus alterTableSetColumnProperties(final TAlterOrDropTableReq req) {
+ final String columnName = ReadWriteIOUtils.readString(req.updateInfo);
+ final SetTableColumnPropertiesProcedure procedure =
+ new SetTableColumnPropertiesProcedure(
+ req.database,
+ req.tableName,
+ columnName,
+ req.queryId,
+ ReadWriteIOUtils.readMap(req.updateInfo),
+ false);
+ return executeWithoutDuplicate(
+ req.database,
+ null,
+ req.tableName,
+ req.queryId,
+ ProcedureType.SET_TABLE_COLUMN_PROPERTIES_PROCEDURE,
+ procedure);
+ }
+
public TSStatus alterTableRenameColumn(final TAlterOrDropTableReq req) {
final boolean isView = req.isSetIsView() && req.isIsView();
return executeWithoutDuplicate(
@@ -2652,6 +2672,7 @@ public class ProcedureManager {
case ADD_VIEW_COLUMN_PROCEDURE:
case SET_TABLE_PROPERTIES_PROCEDURE:
case SET_VIEW_PROPERTIES_PROCEDURE:
+ case SET_TABLE_COLUMN_PROPERTIES_PROCEDURE:
case RENAME_TABLE_COLUMN_PROCEDURE:
case RENAME_VIEW_COLUMN_PROCEDURE:
case DROP_TABLE_COLUMN_PROCEDURE:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
index 86f2320b344..936e54e00db 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
@@ -79,6 +79,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.CommitDeleteTab
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTableColumnPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.AddTableViewColumnPlan;
@@ -116,6 +117,7 @@ import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableColumnPr
import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableProcedure;
+import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTableColumnPropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTablePropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.AddViewColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.CreateTableViewProcedure;
@@ -572,6 +574,7 @@ public class IoTDBConfigNodeReceiver extends IoTDBFileReceiver {
case AddTableColumn:
case AddViewColumn:
case SetTableProperties:
+ case SetTableColumnProperties:
case SetViewProperties:
case CommitDeleteColumn:
case CommitDeleteViewColumn:
@@ -1034,6 +1037,22 @@ public class IoTDBConfigNodeReceiver extends IoTDBFileReceiver {
queryId,
((SetTablePropertiesPlan) plan).getProperties(),
shouldMarkAsPipeRequest.get()));
+ case SetTableColumnProperties:
+ return configManager
+ .getProcedureManager()
+ .executeWithoutDuplicate(
+ ((SetTableColumnPropertiesPlan) plan).getDatabase(),
+ null,
+ ((SetTableColumnPropertiesPlan) plan).getTableName(),
+ queryId,
+ ProcedureType.SET_TABLE_COLUMN_PROPERTIES_PROCEDURE,
+ new SetTableColumnPropertiesProcedure(
+ ((SetTableColumnPropertiesPlan) plan).getDatabase(),
+ ((SetTableColumnPropertiesPlan) plan).getTableName(),
+ ((SetTableColumnPropertiesPlan) plan).getColumnName(),
+ queryId,
+ ((SetTableColumnPropertiesPlan) plan).getProperties(),
+ shouldMarkAsPipeRequest.get()));
case SetViewProperties:
return configManager
.getProcedureManager()
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/visitor/PipeConfigPhysicalPlanTSStatusVisitor.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/visitor/PipeConfigPhysicalPlanTSStatusVisitor.java
index b8607126e99..3b315b7ba3e 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/visitor/PipeConfigPhysicalPlanTSStatusVisitor.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/visitor/PipeConfigPhysicalPlanTSStatusVisitor.java
@@ -42,6 +42,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.CommitDeleteTab
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTableColumnPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.template.CommitSetSchemaTemplatePlan;
@@ -536,6 +537,12 @@ public class PipeConfigPhysicalPlanTSStatusVisitor
return visitCommonTablePlan(setTablePropertiesPlan, context);
}
+ @Override
+ public TSStatus visitSetTableColumnProperties(
+ final SetTableColumnPropertiesPlan setTableColumnPropertiesPlan, final TSStatus context) {
+ return visitCommonTablePlan(setTableColumnPropertiesPlan, context);
+ }
+
@Override
public TSStatus visitCommitDeleteColumn(
final CommitDeleteColumnPlan commitDeleteColumnPlan, final TSStatus context) {
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/ConfigRegionListeningFilter.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/ConfigRegionListeningFilter.java
index ff2cdd5649f..30daf6c9a88 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/ConfigRegionListeningFilter.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/ConfigRegionListeningFilter.java
@@ -124,6 +124,7 @@ public class ConfigRegionListeningFilter {
Collections.unmodifiableList(
Arrays.asList(
ConfigPhysicalPlanType.SetTableProperties,
+ ConfigPhysicalPlanType.SetTableColumnProperties,
ConfigPhysicalPlanType.SetViewProperties,
ConfigPhysicalPlanType.SetTableComment,
ConfigPhysicalPlanType.SetViewComment,
@@ -287,6 +288,7 @@ public class ConfigRegionListeningFilter {
case AddTableColumn:
case AddViewColumn:
case SetTableProperties:
+ case SetTableColumnProperties:
case SetViewProperties:
case SetTableComment:
case SetViewComment:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
index 840be42d48c..0e88a2712b9 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
@@ -1837,6 +1837,61 @@ public class ClusterSchemaManager {
return new Pair<>(RpcUtils.SUCCESS_STATUS, updatedTable);
}
+ public synchronized Pair<TSStatus, TsTable> updateTableColumnProperties(
+ final String database,
+ final String tableName,
+ final String columnName,
+ final Map<String, String> originalProperties,
+ final Map<String, String> updatedProperties)
+ throws MetadataException {
+ final TsTable originalTable = getTableIfExists(database, tableName).orElse(null);
+
+ if (Objects.isNull(originalTable)) {
+ return new Pair<>(
+ RpcUtils.getStatus(
+ TSStatusCode.TABLE_NOT_EXISTS,
+ String.format("Table '%s.%s' does not exist", database, tableName)),
+ null);
+ }
+
+ final Optional<Pair<TSStatus, TsTable>> result =
+ checkTable4View(database, originalTable, false);
+ if (result.isPresent()) {
+ return result.get();
+ }
+
+ if (Objects.isNull(originalTable.getColumnSchema(columnName))) {
+ return new Pair<>(
+ RpcUtils.getStatus(
+ TSStatusCode.COLUMN_NOT_EXISTS,
+ String.format("Column '%s' does not exist", columnName)),
+ null);
+ }
+
+ final TsTable updatedTable = new TsTable(originalTable);
+ final TsTableColumnSchema updatedColumn = updatedTable.getColumnSchema(columnName);
+ updatedProperties
+ .keySet()
+ .removeIf(
+ key -> Objects.equals(updatedProperties.get(key), updatedColumn.getProps().get(key)));
+ if (updatedProperties.isEmpty()) {
+ return new Pair<>(RpcUtils.SUCCESS_STATUS, null);
+ }
+
+ for (final Map.Entry<String, String> entry : updatedProperties.entrySet()) {
+ final String key = entry.getKey();
+ final String value = entry.getValue();
+ originalProperties.put(key, updatedColumn.getProps().get(key));
+ if (Objects.nonNull(value)) {
+ updatedColumn.getProps().put(key, value);
+ } else {
+ updatedColumn.getProps().remove(key);
+ }
+ }
+
+ return new Pair<>(RpcUtils.SUCCESS_STATUS, updatedTable);
+ }
+
private void invalidateLastCache(final String database) {
final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
getNodeManager().getRegisteredDataNodeLocations();
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
index 58bf86d6858..a09c283a48d 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
@@ -136,6 +136,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackCreateTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackPreDeleteTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.PreCreateTableViewPlan;
@@ -588,6 +589,9 @@ public class ConfigPlanExecutor {
case SetTableProperties:
case SetViewProperties:
return clusterSchemaInfo.setTableProperties((SetTablePropertiesPlan) physicalPlan);
+ case SetTableColumnProperties:
+ return clusterSchemaInfo.setTableColumnProperties(
+ (SetTableColumnPropertiesPlan) physicalPlan);
case PreDeleteColumn:
case PreDeleteViewColumn:
return clusterSchemaInfo.preDeleteColumn((PreDeleteColumnPlan) physicalPlan);
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
index 1b9c880cd6a..3e900eca55c 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
@@ -69,6 +69,7 @@ import org.apache.iotdb.confignode.consensus.request.write.table.RenameTablePlan
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackCreateTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.RollbackPreDeleteTablePlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnCommentPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTableCommentPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.PreCreateTableViewPlan;
@@ -1593,6 +1594,16 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
plan.getProperties()));
}
+ public TSStatus setTableColumnProperties(final SetTableColumnPropertiesPlan plan) {
+ return executeWithLock(
+ () ->
+ tableModelMTree.setTableColumnProperties(
+ getQualifiedDatabasePartialPath(plan.getDatabase()),
+ plan.getTableName(),
+ plan.getColumnName(),
+ plan.getProperties()));
+ }
+
public TSStatus preDeleteColumn(final PreDeleteColumnPlan plan) {
databaseReadWriteLock.writeLock().lock();
try {
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java
index 12f6a2baaa1..53536aa361c 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java
@@ -980,6 +980,28 @@ public class ConfigMTree {
});
}
+ public void setTableColumnProperties(
+ final PartialPath database,
+ final String tableName,
+ final String columnName,
+ final Map<String, String> properties)
+ throws MetadataException {
+ final TsTable table = getTableNode(database, tableName).getTable();
+ final TsTableColumnSchema columnSchema = table.getColumnSchema(columnName);
+ if (Objects.isNull(columnSchema)) {
+ throw new ColumnNotExistsException(
+ PathUtils.unQualifyDatabaseName(database.getFullPath()), tableName, columnName);
+ }
+ properties.forEach(
+ (key, value) -> {
+ if (Objects.nonNull(value)) {
+ columnSchema.getProps().put(key, value);
+ } else {
+ columnSchema.getProps().remove(key);
+ }
+ });
+ }
+
// Return true if removed column is an attribute column
// false if measurement column
public boolean preDeleteColumn(
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/AbstractSetPropertiesProcedure.java
similarity index 76%
copy from iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
copy to iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/AbstractSetPropertiesProcedure.java
index 27e75e6c28c..be6f67007a3 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/AbstractSetPropertiesProcedure.java
@@ -23,14 +23,11 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.commons.exception.IoTDBException;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.schema.table.TsTable;
-import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
-import org.apache.iotdb.confignode.consensus.request.write.table.view.SetViewPropertiesPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
import org.apache.iotdb.confignode.i18n.ProcedureMessages;
import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
-import org.apache.iotdb.confignode.procedure.impl.schema.table.view.SetViewPropertiesProcedure;
import org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState;
-import org.apache.iotdb.confignode.procedure.store.ProcedureType;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.tsfile.utils.Pair;
@@ -50,19 +47,20 @@ import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropert
import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.SET_PROPERTIES;
import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.VALIDATE_TABLE;
-public class SetTablePropertiesProcedure
+public abstract class AbstractSetPropertiesProcedure
extends AbstractAlterOrDropTableProcedure<SetTablePropertiesState> {
- private static final Logger LOGGER = LoggerFactory.getLogger(SetTablePropertiesProcedure.class);
+ private static final Logger LOGGER =
+ LoggerFactory.getLogger(AbstractSetPropertiesProcedure.class);
- private Map<String, String> originalProperties = new HashMap<>();
- private Map<String, String> updatedProperties;
+ protected Map<String, String> originalProperties = new HashMap<>();
+ protected Map<String, String> updatedProperties;
- public SetTablePropertiesProcedure(final boolean isGeneratedByPipe) {
+ protected AbstractSetPropertiesProcedure(final boolean isGeneratedByPipe) {
super(isGeneratedByPipe);
}
- public SetTablePropertiesProcedure(
+ protected AbstractSetPropertiesProcedure(
final String database,
final String tableName,
final String queryId,
@@ -125,17 +123,9 @@ public class SetTablePropertiesProcedure
}
}
- private void validateTable(final ConfigNodeProcedureEnv env) {
+ public void validateTable(final ConfigNodeProcedureEnv env) {
try {
- final Pair<TSStatus, TsTable> result =
- env.getConfigManager()
- .getClusterSchemaManager()
- .updateTableProperties(
- database,
- tableName,
- originalProperties,
- updatedProperties,
- this instanceof SetViewPropertiesProcedure);
+ final Pair<TSStatus, TsTable> result = updateProperties(env);
final TSStatus status = result.getLeft();
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
setFailure(new ProcedureException(new IoTDBException(status)));
@@ -148,6 +138,9 @@ public class SetTablePropertiesProcedure
}
}
+ protected abstract Pair<TSStatus, TsTable> updateProperties(ConfigNodeProcedureEnv env)
+ throws MetadataException;
+
@Override
protected void preRelease(final ConfigNodeProcedureEnv env) {
super.preRelease(env);
@@ -158,11 +151,7 @@ public class SetTablePropertiesProcedure
final TSStatus status =
env.getConfigManager()
.getClusterSchemaManager()
- .executePlan(
- this instanceof SetViewPropertiesProcedure
- ? new SetViewPropertiesPlan(database, tableName, updatedProperties)
- : new SetTablePropertiesPlan(database, tableName, updatedProperties),
- isGeneratedByPipe);
+ .executePlan(createSetPropertiesPlan(updatedProperties, false), isGeneratedByPipe);
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
setFailure(new ProcedureException(new IoTDBException(status)));
} else {
@@ -170,10 +159,8 @@ public class SetTablePropertiesProcedure
}
}
- @Override
- protected String getActionMessage() {
- return "set table properties";
- }
+ protected abstract ConfigPhysicalPlan createSetPropertiesPlan(
+ Map<String, String> properties, boolean isRollback);
@Override
protected void rollbackState(
@@ -212,11 +199,7 @@ public class SetTablePropertiesProcedure
final TSStatus status =
env.getConfigManager()
.getClusterSchemaManager()
- .executePlan(
- this instanceof SetViewPropertiesProcedure
- ? new SetViewPropertiesPlan(database, tableName, originalProperties)
- : new SetTablePropertiesPlan(database, tableName, originalProperties),
- isGeneratedByPipe);
+ .executePlan(createSetPropertiesPlan(originalProperties, true), isGeneratedByPipe);
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
setFailure(new ProcedureException(new IoTDBException(status)));
}
@@ -237,26 +220,17 @@ public class SetTablePropertiesProcedure
return VALIDATE_TABLE;
}
- @Override
- public void serialize(final DataOutputStream stream) throws IOException {
- stream.writeShort(
- isGeneratedByPipe
- ? ProcedureType.PIPE_ENRICHED_SET_TABLE_PROPERTIES_PROCEDURE.getTypeCode()
- : ProcedureType.SET_TABLE_PROPERTIES_PROCEDURE.getTypeCode());
- innerSerialize(stream);
- }
-
protected void innerSerialize(final DataOutputStream stream) throws IOException {
super.serialize(stream);
+ serializeProperties(stream);
+ }
+ protected void serializeProperties(final DataOutputStream stream) throws IOException {
ReadWriteIOUtils.write(originalProperties, stream);
ReadWriteIOUtils.write(updatedProperties, stream);
}
- @Override
- public void deserialize(final ByteBuffer byteBuffer) {
- super.deserialize(byteBuffer);
-
+ protected void deserializeProperties(final ByteBuffer byteBuffer) {
this.originalProperties = ReadWriteIOUtils.readMap(byteBuffer);
this.updatedProperties = ReadWriteIOUtils.readMap(byteBuffer);
}
@@ -264,7 +238,8 @@ public class SetTablePropertiesProcedure
@Override
public boolean equals(final Object o) {
return super.equals(o)
- && Objects.equals(updatedProperties, ((SetTablePropertiesProcedure) o).updatedProperties);
+ && Objects.equals(
+ updatedProperties, ((AbstractSetPropertiesProcedure) o).updatedProperties);
}
@Override
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTableColumnPropertiesProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTableColumnPropertiesProcedure.java
new file mode 100644
index 00000000000..996b192e343
--- /dev/null
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTableColumnPropertiesProcedure.java
@@ -0,0 +1,107 @@
+/*
+ * 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.confignode.procedure.impl.schema.table;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.write.table.SetTableColumnPropertiesPlan;
+import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
+import org.apache.iotdb.confignode.procedure.store.ProcedureType;
+
+import org.apache.tsfile.utils.Pair;
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Objects;
+
+public class SetTableColumnPropertiesProcedure extends AbstractSetPropertiesProcedure {
+
+ private String columnName;
+
+ public SetTableColumnPropertiesProcedure(final boolean isGeneratedByPipe) {
+ super(isGeneratedByPipe);
+ }
+
+ public SetTableColumnPropertiesProcedure(
+ final String database,
+ final String tableName,
+ final String columnName,
+ final String queryId,
+ final Map<String, String> properties,
+ final boolean isGeneratedByPipe) {
+ super(database, tableName, queryId, properties, isGeneratedByPipe);
+ this.columnName = columnName;
+ }
+
+ @Override
+ protected Pair<TSStatus, TsTable> updateProperties(final ConfigNodeProcedureEnv env)
+ throws MetadataException {
+ return env.getConfigManager()
+ .getClusterSchemaManager()
+ .updateTableColumnProperties(
+ database, tableName, columnName, originalProperties, updatedProperties);
+ }
+
+ @Override
+ protected ConfigPhysicalPlan createSetPropertiesPlan(
+ final Map<String, String> properties, final boolean isRollback) {
+ return new SetTableColumnPropertiesPlan(
+ database, tableName, columnName, properties, isRollback);
+ }
+
+ @Override
+ protected String getActionMessage() {
+ return "set table column properties";
+ }
+
+ @Override
+ public void serialize(final DataOutputStream stream) throws IOException {
+ stream.writeShort(
+ isGeneratedByPipe
+ ? ProcedureType.PIPE_ENRICHED_SET_TABLE_COLUMN_PROPERTIES_PROCEDURE.getTypeCode()
+ : ProcedureType.SET_TABLE_COLUMN_PROPERTIES_PROCEDURE.getTypeCode());
+ super.serialize(stream);
+ ReadWriteIOUtils.write(columnName, stream);
+ serializeProperties(stream);
+ }
+
+ @Override
+ public void deserialize(final ByteBuffer byteBuffer) {
+ super.deserialize(byteBuffer);
+ this.columnName = ReadWriteIOUtils.readString(byteBuffer);
+ deserializeProperties(byteBuffer);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ return super.equals(o)
+ && Objects.equals(columnName, ((SetTableColumnPropertiesProcedure) o).columnName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), columnName);
+ }
+}
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
index 27e75e6c28c..8cf3026d043 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
@@ -20,43 +20,23 @@
package org.apache.iotdb.confignode.procedure.impl.schema.table;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
-import org.apache.iotdb.commons.exception.IoTDBException;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.SetTablePropertiesPlan;
import org.apache.iotdb.confignode.consensus.request.write.table.view.SetViewPropertiesPlan;
-import org.apache.iotdb.confignode.i18n.ProcedureMessages;
import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
-import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.SetViewPropertiesProcedure;
-import org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState;
import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.tsfile.utils.Pair;
-import org.apache.tsfile.utils.ReadWriteIOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
-import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.COMMIT_RELEASE;
-import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.PRE_RELEASE;
-import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.SET_PROPERTIES;
-import static org.apache.iotdb.confignode.procedure.state.schema.SetTablePropertiesState.VALIDATE_TABLE;
-
-public class SetTablePropertiesProcedure
- extends AbstractAlterOrDropTableProcedure<SetTablePropertiesState> {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SetTablePropertiesProcedure.class);
-
- private Map<String, String> originalProperties = new HashMap<>();
- private Map<String, String> updatedProperties;
+public class SetTablePropertiesProcedure extends AbstractSetPropertiesProcedure {
public SetTablePropertiesProcedure(final boolean isGeneratedByPipe) {
super(isGeneratedByPipe);
@@ -68,106 +48,28 @@ public class SetTablePropertiesProcedure
final String queryId,
final Map<String, String> properties,
final boolean isGeneratedByPipe) {
- super(database, tableName, queryId, isGeneratedByPipe);
- this.updatedProperties = properties;
+ super(database, tableName, queryId, properties, isGeneratedByPipe);
}
@Override
- protected Flow executeFromState(
- final ConfigNodeProcedureEnv env, final SetTablePropertiesState state)
- throws InterruptedException {
- final long startTime = System.currentTimeMillis();
- try {
- switch (state) {
- case VALIDATE_TABLE:
- validateTable(env);
- LOGGER.info(
- ProcedureMessages.VALIDATE_TABLE_FOR_TABLE_WHEN_SETTING_PROPERTIES,
- database,
- tableName);
- if (!isFailed() && Objects.isNull(table)) {
- LOGGER.info(
- ProcedureMessages.THE_UPDATED_TABLE_HAS_THE_SAME_PROPERTIES_WITH_THE_ORIGINAL);
- return Flow.NO_MORE_STATE;
- }
- break;
- case PRE_RELEASE:
- preRelease(env);
- LOGGER.info(
- ProcedureMessages.PRE_RELEASE_INFO_FOR_TABLE_WHEN_SETTING_PROPERTIES,
- database,
- tableName);
- break;
- case SET_PROPERTIES:
- setProperties(env);
- LOGGER.info(ProcedureMessages.SET_PROPERTIES_TO_TABLE, database, tableName);
- break;
- case COMMIT_RELEASE:
- commitRelease(env);
- LOGGER.info(
- ProcedureMessages.COMMIT_RELEASE_INFO_OF_TABLE_WHEN_SETTING_PROPERTIES,
- database,
- tableName);
- return Flow.NO_MORE_STATE;
- default:
- setFailure(
- new ProcedureException(ProcedureMessages.UNRECOGNIZED_ADDTABLECOLUMNSTATE + state));
- return Flow.NO_MORE_STATE;
- }
- return Flow.HAS_MORE_STATE;
- } finally {
- LOGGER.info(
- ProcedureMessages.SETTABLEPROPERTIES_COSTS_MS,
- database,
- tableName,
- state,
- (System.currentTimeMillis() - startTime));
- }
- }
-
- private void validateTable(final ConfigNodeProcedureEnv env) {
- try {
- final Pair<TSStatus, TsTable> result =
- env.getConfigManager()
- .getClusterSchemaManager()
- .updateTableProperties(
- database,
- tableName,
- originalProperties,
- updatedProperties,
- this instanceof SetViewPropertiesProcedure);
- final TSStatus status = result.getLeft();
- if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
- setFailure(new ProcedureException(new IoTDBException(status)));
- return;
- }
- table = result.getRight();
- setNextState(PRE_RELEASE);
- } catch (final MetadataException e) {
- setFailure(new ProcedureException(e));
- }
+ protected Pair<TSStatus, TsTable> updateProperties(final ConfigNodeProcedureEnv env)
+ throws MetadataException {
+ return env.getConfigManager()
+ .getClusterSchemaManager()
+ .updateTableProperties(
+ database,
+ tableName,
+ originalProperties,
+ updatedProperties,
+ this instanceof SetViewPropertiesProcedure);
}
@Override
- protected void preRelease(final ConfigNodeProcedureEnv env) {
- super.preRelease(env);
- setNextState(SET_PROPERTIES);
- }
-
- private void setProperties(final ConfigNodeProcedureEnv env) {
- final TSStatus status =
- env.getConfigManager()
- .getClusterSchemaManager()
- .executePlan(
- this instanceof SetViewPropertiesProcedure
- ? new SetViewPropertiesPlan(database, tableName, updatedProperties)
- : new SetTablePropertiesPlan(database, tableName, updatedProperties),
- isGeneratedByPipe);
- if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
- setFailure(new ProcedureException(new IoTDBException(status)));
- } else {
- setNextState(COMMIT_RELEASE);
- }
+ protected ConfigPhysicalPlan createSetPropertiesPlan(
+ final Map<String, String> properties, final boolean isRollback) {
+ return this instanceof SetViewPropertiesProcedure
+ ? new SetViewPropertiesPlan(database, tableName, properties)
+ : new SetTablePropertiesPlan(database, tableName, properties);
}
@Override
@@ -175,68 +77,6 @@ public class SetTablePropertiesProcedure
return "set table properties";
}
- @Override
- protected void rollbackState(
- final ConfigNodeProcedureEnv env, final SetTablePropertiesState state)
- throws IOException, InterruptedException, ProcedureException {
- final long startTime = System.currentTimeMillis();
- try {
- switch (state) {
- case PRE_RELEASE:
- LOGGER.info(
- ProcedureMessages.START_ROLLBACK_PRE_RELEASE_INFO_FOR_TABLE_WHEN_SETTING_PROPERTIES,
- database,
- table.getTableName());
- rollbackPreRelease(env);
- break;
- case SET_PROPERTIES:
- LOGGER.info(
- ProcedureMessages.START_ROLLBACK_SET_PROPERTIES_TO_TABLE,
- database,
- table.getTableName());
- rollbackSetProperties(env);
- break;
- }
- } finally {
- LOGGER.info(
- ProcedureMessages.ROLLBACK_SETTABLEPROPERTIES_COSTS_MS,
- state,
- (System.currentTimeMillis() - startTime));
- }
- }
-
- private void rollbackSetProperties(final ConfigNodeProcedureEnv env) {
- if (table == null) {
- return;
- }
- final TSStatus status =
- env.getConfigManager()
- .getClusterSchemaManager()
- .executePlan(
- this instanceof SetViewPropertiesProcedure
- ? new SetViewPropertiesPlan(database, tableName, originalProperties)
- : new SetTablePropertiesPlan(database, tableName, originalProperties),
- isGeneratedByPipe);
- if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
- setFailure(new ProcedureException(new IoTDBException(status)));
- }
- }
-
- @Override
- protected SetTablePropertiesState getState(final int stateId) {
- return SetTablePropertiesState.values()[stateId];
- }
-
- @Override
- protected int getStateId(final SetTablePropertiesState state) {
- return state.ordinal();
- }
-
- @Override
- protected SetTablePropertiesState getInitialState() {
- return VALIDATE_TABLE;
- }
-
@Override
public void serialize(final DataOutputStream stream) throws IOException {
stream.writeShort(
@@ -246,29 +86,9 @@ public class SetTablePropertiesProcedure
innerSerialize(stream);
}
- protected void innerSerialize(final DataOutputStream stream) throws IOException {
- super.serialize(stream);
-
- ReadWriteIOUtils.write(originalProperties, stream);
- ReadWriteIOUtils.write(updatedProperties, stream);
- }
-
@Override
public void deserialize(final ByteBuffer byteBuffer) {
super.deserialize(byteBuffer);
-
- this.originalProperties = ReadWriteIOUtils.readMap(byteBuffer);
- this.updatedProperties = ReadWriteIOUtils.readMap(byteBuffer);
- }
-
- @Override
- public boolean equals(final Object o) {
- return super.equals(o)
- && Objects.equals(updatedProperties, ((SetTablePropertiesProcedure) o).updatedProperties);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(), updatedProperties);
+ deserializeProperties(byteBuffer);
}
}
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
index 165b048b636..0f6b2fa75e1 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
@@ -62,6 +62,7 @@ import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableColumnPr
import org.apache.iotdb.confignode.procedure.impl.schema.table.DropTableProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.RenameTableProcedure;
+import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTableColumnPropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.SetTablePropertiesProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.AddViewColumnProcedure;
import org.apache.iotdb.confignode.procedure.impl.schema.table.view.CreateTableViewProcedure;
@@ -237,6 +238,9 @@ public class ProcedureFactory implements IProcedureFactory {
case SET_VIEW_PROPERTIES_PROCEDURE:
procedure = new SetViewPropertiesProcedure(false);
break;
+ case SET_TABLE_COLUMN_PROPERTIES_PROCEDURE:
+ procedure = new SetTableColumnPropertiesProcedure(false);
+ break;
case RENAME_TABLE_COLUMN_PROCEDURE:
procedure = new RenameTableColumnProcedure(false);
break;
@@ -318,6 +322,9 @@ public class ProcedureFactory implements IProcedureFactory {
case PIPE_ENRICHED_SET_TABLE_PROPERTIES_PROCEDURE:
procedure = new SetTablePropertiesProcedure(true);
break;
+ case PIPE_ENRICHED_SET_TABLE_COLUMN_PROPERTIES_PROCEDURE:
+ procedure = new SetTableColumnPropertiesProcedure(true);
+ break;
case PIPE_ENRICHED_RENAME_TABLE_COLUMN_PROCEDURE:
procedure = new RenameTableColumnProcedure(true);
break;
@@ -498,6 +505,8 @@ public class ProcedureFactory implements IProcedureFactory {
return ProcedureType.SET_VIEW_PROPERTIES_PROCEDURE;
} else if (procedure instanceof SetTablePropertiesProcedure) {
return ProcedureType.SET_TABLE_PROPERTIES_PROCEDURE;
+ } else if (procedure instanceof SetTableColumnPropertiesProcedure) {
+ return ProcedureType.SET_TABLE_COLUMN_PROPERTIES_PROCEDURE;
} else if (procedure instanceof RenameViewColumnProcedure) {
return ProcedureType.RENAME_VIEW_COLUMN_PROCEDURE;
} else if (procedure instanceof RenameTableColumnProcedure) {
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/AlterOrDropTableOperationType.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/AlterOrDropTableOperationType.java
index 46a8d5ddf3e..13f9d51798d 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/AlterOrDropTableOperationType.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/AlterOrDropTableOperationType.java
@@ -28,7 +28,8 @@ public enum AlterOrDropTableOperationType {
DROP_TABLE((byte) 5),
COMMENT_TABLE((byte) 6),
COMMENT_COLUMN((byte) 7),
- ALTER_COLUMN_DATA_TYPE((byte) 8);
+ ALTER_COLUMN_DATA_TYPE((byte) 8),
+ SET_COLUMN_PROPERTIES((byte) 9);
private final byte type;
@@ -60,6 +61,8 @@ public enum AlterOrDropTableOperationType {
return COMMENT_COLUMN;
case 8:
return ALTER_COLUMN_DATA_TYPE;
+ case 9:
+ return SET_COLUMN_PROPERTIES;
default:
throw new IllegalArgumentException();
}
(iotdb) 03/10: [RPC] Reserve LBAC status codes
Posted by sh...@apache.org.
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
commit a35888795719f79e6566b1f1216f9fec8766297d
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 14:39:16 2026 +0800
[RPC] Reserve LBAC status codes
---
.../java/org/apache/iotdb/rpc/TSStatusCode.java | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index 61431249eb3..e4c42b91c05 100644
--- a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -366,6 +366,28 @@ public enum TSStatusCode {
EXTERNAL_SERVICE_INSTANCE_CREATE_ERROR(2303),
CANNOT_DROP_BUILTIN_EXTERNAL_SERVICE(2304),
CANNOT_DROP_RUNNING_EXTERNAL_SERVICE(2305),
+
+ // LBAC
+ LBAC_ACCESS_DENIED(2400),
+ COMPONENT_NOT_EXISTS(2401),
+ COMPONENT_ALREADY_EXISTS(2402),
+ POLICY_NOT_EXISTS(2403),
+ POLICY_ALREADY_EXISTS(2404),
+ LABEL_NOT_EXISTS(2405),
+ LABEL_ALREADY_EXISTS(2406),
+ ELEMENT_NOT_EXISTS(2407),
+ ELEMENT_ALREADY_EXISTS(2408),
+ INVALID_COMPONENT_TYPE(2409),
+ INVALID_ELEMENT_CLAUSE(2410),
+ INVALID_COMMENT_TARGET(2411),
+ COMPONENT_IS_REFERENCED(2412),
+ POLICY_IS_REFERENCED(2413),
+ LABEL_IS_REFERENCED(2414),
+ POLICY_NOT_SET(2415),
+ POLICY_ALREADY_SET(2416),
+ POLICY_CONFLICT(2417),
+ LABEL_NOT_SET(2418),
+ INVALID_LABEL_VALUE(2419),
;
private final int statusCode;
(iotdb) 08/10: [Query] Log LBAC access errors at info level
Posted by sh...@apache.org.
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
commit 2d75ef3747fbed5f62fb23ff819076d9f1ae64df
Author: shuwenwei <s1...@gmail.com>
AuthorDate: Thu Sep 17 16:03:18 2026 +0800
[Query] Log LBAC access errors at info level
---
.../src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
index b6154b059d5..cff45b29b9a 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
@@ -116,6 +116,8 @@ public class ErrorHandlingUtils {
if (status.getCode() == TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
|| status.getCode() == TSStatusCode.SEMANTIC_ERROR.getStatusCode()
|| status.getCode() == TSStatusCode.NO_PERMISSION.getStatusCode()
+ || (status.getCode() >= TSStatusCode.LBAC_ACCESS_DENIED.getStatusCode()
+ && status.getCode() <= TSStatusCode.INVALID_LABEL_VALUE.getStatusCode())
|| status.getCode() == TSStatusCode.ILLEGAL_PATH.getStatusCode()
|| status.getCode() == TSStatusCode.NUMERIC_VALUE_OUT_OF_RANGE.getStatusCode()
|| status.getCode() == TSStatusCode.DIVISION_BY_ZERO.getStatusCode()