You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2022/07/09 01:49:30 UTC
[iotdb] branch master updated: [IOTDB-3560]Support basic create and query template (#6608)
This is an automated email from the ASF dual-hosted git repository.
zyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 63de9af1eb [IOTDB-3560]Support basic create and query template (#6608)
63de9af1eb is described below
commit 63de9af1eb69d5b80f5b803dd48cd55b69e5c21f
Author: yunchan86 <yu...@163.com>
AuthorDate: Sat Jul 9 09:49:24 2022 +0800
[IOTDB-3560]Support basic create and query template (#6608)
[IOTDB-3560]Support basic create and query template #6608
---
.../consensus/request/ConfigPhysicalPlan.java | 12 ++
.../consensus/request/ConfigPhysicalPlanType.java | 7 +-
.../request/read/GetNodesInSchemaTemplatePlan.java | 77 ++++++++
.../request/read/GetSchemaTemplatePlan.java | 54 +++++
.../request/write/CreateSchemaTemplatePlan.java | 74 +++++++
.../consensus/response/TemplateInfoResp.java | 48 +++++
.../confignode/manager/ClusterSchemaManager.java | 76 +++++++
.../iotdb/confignode/manager/ConfigManager.java | 36 ++++
.../apache/iotdb/confignode/manager/IManager.java | 26 +++
.../confignode/persistence/ClusterSchemaInfo.java | 63 ++++++
.../persistence/executor/ConfigPlanExecutor.java | 9 +
.../persistence/schema/TemplateTable.java | 219 +++++++++++++++++++++
.../thrift/ConfigNodeRPCServiceProcessor.java | 18 ++
.../request/ConfigPhysicalPlanSerDeTest.java | 55 ++++++
.../confignode/persistence/TemplateTableTest.java | 135 +++++++++++++
.../apache/iotdb/db/client/ConfigNodeClient.java | 51 +++++
.../metadata/template/ClusterTemplateManager.java | 161 +++++++++++++++
.../db/metadata/template/ITemplateManager.java | 49 +++++
.../iotdb/db/metadata/template/Template.java | 37 +++-
.../iotdb/db/mpp/common/header/HeaderConstant.java | 23 +++
.../apache/iotdb/db/mpp/plan/analyze/Analyzer.java | 40 ++++
.../iotdb/db/mpp/plan/constant/StatementType.java | 2 +
.../plan/execution/config/ConfigTaskVisitor.java | 21 ++
.../execution/config/CreateSchemaTemplateTask.java | 40 ++++
.../config/ShowNodesInSchemaTemplateTask.java | 79 ++++++++
.../execution/config/ShowSchemaTemplateTask.java | 67 +++++++
.../config/executor/ClusterConfigTaskExecutor.java | 67 +++++++
.../config/executor/IConfigTaskExecutor.java | 12 ++
.../executor/StandaloneConfigTaskExecutor.java | 39 ++++
.../iotdb/db/mpp/plan/parser/ASTVisitor.java | 158 +++++++++++++++
.../db/mpp/plan/statement/StatementVisitor.java | 23 ++-
.../template/CreateSchemaTemplateStatement.java | 181 +++++++++++++++++
.../ShowNodesInSchemaTemplateStatement.java | 55 ++++++
.../template/ShowSchemaTemplateStatement.java | 44 +++++
.../java/org/apache/iotdb/rpc/TSStatusCode.java | 2 +
.../src/main/thrift/confignode.thrift | 25 +++
36 files changed, 2079 insertions(+), 6 deletions(-)
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
index 55b4289994..af8050f6f1 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
@@ -23,10 +23,12 @@ import org.apache.iotdb.confignode.consensus.request.read.CountStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataNodeInfoPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetNodePathsPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetNodesInSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetOrCreateDataPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetOrCreateSchemaPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetSchemaPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.ActivateDataNodePlan;
import org.apache.iotdb.confignode.consensus.request.write.AdjustMaxRegionGroupCountPlan;
@@ -35,6 +37,7 @@ import org.apache.iotdb.confignode.consensus.request.write.CreateDataPartitionPl
import org.apache.iotdb.confignode.consensus.request.write.CreateFunctionPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateRegionGroupsPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteProcedurePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteRegionsPlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteStorageGroupPlan;
@@ -199,6 +202,15 @@ public abstract class ConfigPhysicalPlan implements IConsensusRequest {
case DropFunction:
req = new DropFunctionPlan();
break;
+ case CreateSchemaTemplate:
+ req = new CreateSchemaTemplatePlan();
+ break;
+ case ShowSchemaTemplate:
+ req = new GetSchemaTemplatePlan();
+ break;
+ case ShowNodesInSchemaTemplate:
+ req = new GetNodesInSchemaTemplatePlan();
+ break;
case GetNodePathsPartition:
req = new GetNodePathsPartitionPlan();
break;
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
index 6262e45dba..31bdf30554 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
@@ -64,7 +64,10 @@ public enum ConfigPhysicalPlanType {
RemoveConfigNode,
CreateFunction,
DropFunction,
- GetNodePathsPartition,
GetRegionInfoList,
- GetDataNodesInfoList;
+ GetDataNodesInfoList,
+ GetNodePathsPartition,
+ CreateSchemaTemplate,
+ ShowSchemaTemplate,
+ ShowNodesInSchemaTemplate;
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetNodesInSchemaTemplatePlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetNodesInSchemaTemplatePlan.java
new file mode 100644
index 0000000000..058e33436a
--- /dev/null
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetNodesInSchemaTemplatePlan.java
@@ -0,0 +1,77 @@
+/*
+ * 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.read;
+
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+public class GetNodesInSchemaTemplatePlan extends ConfigPhysicalPlan {
+
+ private String templateName;
+
+ public GetNodesInSchemaTemplatePlan() {
+ super(ConfigPhysicalPlanType.ShowNodesInSchemaTemplate);
+ }
+
+ public GetNodesInSchemaTemplatePlan(String templateName) {
+ this();
+ this.templateName = templateName;
+ }
+
+ public String getTemplateName() {
+ return templateName;
+ }
+
+ @Override
+ protected void serializeImpl(DataOutputStream stream) throws IOException {
+ stream.writeInt(ConfigPhysicalPlanType.ShowNodesInSchemaTemplate.ordinal());
+ byte[] bytes = this.getTemplateName().getBytes();
+ int length = bytes.length;
+ stream.writeInt(length);
+ stream.write(bytes);
+ }
+
+ @Override
+ protected void deserializeImpl(ByteBuffer buffer) throws IOException {
+ int length = ReadWriteIOUtils.readInt(buffer);
+ byte[] dataBytes = ReadWriteIOUtils.readBytes(buffer, length);
+ this.templateName = new String(dataBytes, TSFileConfig.STRING_CHARSET);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ GetNodesInSchemaTemplatePlan that = (GetNodesInSchemaTemplatePlan) o;
+ return this.templateName.equalsIgnoreCase(this.templateName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(templateName);
+ }
+}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetSchemaTemplatePlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetSchemaTemplatePlan.java
new file mode 100644
index 0000000000..143422dcba
--- /dev/null
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetSchemaTemplatePlan.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.confignode.consensus.request.read;
+
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+public class GetSchemaTemplatePlan extends ConfigPhysicalPlan {
+
+ public GetSchemaTemplatePlan() {
+ super(ConfigPhysicalPlanType.ShowSchemaTemplate);
+ }
+
+ @Override
+ protected void serializeImpl(DataOutputStream stream) throws IOException {
+ stream.writeInt(ConfigPhysicalPlanType.ShowSchemaTemplate.ordinal());
+ }
+
+ @Override
+ protected void deserializeImpl(ByteBuffer buffer) throws IOException {}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o != null) return true;
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this);
+ }
+}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/CreateSchemaTemplatePlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/CreateSchemaTemplatePlan.java
new file mode 100644
index 0000000000..923471ea91
--- /dev/null
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/CreateSchemaTemplatePlan.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.confignode.consensus.request.write;
+
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class CreateSchemaTemplatePlan extends ConfigPhysicalPlan {
+
+ private byte[] template;
+
+ public CreateSchemaTemplatePlan() {
+ super(ConfigPhysicalPlanType.CreateSchemaTemplate);
+ }
+
+ public CreateSchemaTemplatePlan(byte[] template) {
+ this();
+ this.template = template;
+ }
+
+ public byte[] getTemplate() {
+ return template;
+ }
+
+ @Override
+ protected void serializeImpl(DataOutputStream stream) throws IOException {
+ stream.writeInt(ConfigPhysicalPlanType.CreateSchemaTemplate.ordinal());
+ stream.writeInt(template.length);
+ stream.write(template);
+ }
+
+ @Override
+ protected void deserializeImpl(ByteBuffer buffer) throws IOException {
+ int length = ReadWriteIOUtils.readInt(buffer);
+ this.template = ReadWriteIOUtils.readBytes(buffer, length);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CreateSchemaTemplatePlan that = (CreateSchemaTemplatePlan) o;
+ return Arrays.equals(that.template, template);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(template);
+ }
+}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/TemplateInfoResp.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/TemplateInfoResp.java
new file mode 100644
index 0000000000..c427867b48
--- /dev/null
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/TemplateInfoResp.java
@@ -0,0 +1,48 @@
+/*
+ * 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.response;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.consensus.common.DataSet;
+import org.apache.iotdb.db.metadata.template.Template;
+
+import java.util.List;
+
+public class TemplateInfoResp implements DataSet {
+
+ TSStatus status;
+ List<Template> templateList;
+
+ public TSStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(TSStatus status) {
+ this.status = status;
+ }
+
+ public List<Template> getTemplateList() {
+ return templateList;
+ }
+
+ public void setTemplateList(List<Template> templateList) {
+ this.templateList = templateList;
+ }
+}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
index de7af53548..6280bce6ca 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
@@ -28,18 +28,25 @@ import org.apache.iotdb.confignode.client.AsyncDataNodeClientPool;
import org.apache.iotdb.confignode.client.handlers.SetTTLHandler;
import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
import org.apache.iotdb.confignode.consensus.request.read.CountStorageGroupPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetNodesInSchemaTemplatePlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.AdjustMaxRegionGroupCountPlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetDataReplicationFactorPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetSchemaReplicationFactorPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetTTLPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetTimePartitionIntervalPlan;
+import org.apache.iotdb.confignode.consensus.response.TemplateInfoResp;
import org.apache.iotdb.confignode.exception.StorageGroupNotExistsException;
import org.apache.iotdb.confignode.persistence.ClusterSchemaInfo;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
import org.apache.iotdb.consensus.common.DataSet;
+import org.apache.iotdb.db.metadata.template.Template;
import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.iotdb.tsfile.utils.Pair;
@@ -47,6 +54,9 @@ import org.apache.iotdb.tsfile.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -297,6 +307,72 @@ public class ClusterSchemaManager {
return clusterSchemaInfo.getMaxRegionGroupCount(storageGroup, consensusGroupType);
}
+ /**
+ * create schema template
+ *
+ * @param createSchemaTemplatePlan CreateSchemaTemplatePlan
+ * @return TSStatus
+ */
+ public TSStatus createTemplate(CreateSchemaTemplatePlan createSchemaTemplatePlan) {
+ return getConsensusManager().write(createSchemaTemplatePlan).getStatus();
+ }
+
+ /**
+ * show schema template
+ *
+ * @return TGetAllTemplatesResp
+ */
+ public TGetAllTemplatesResp getAllTemplates() {
+ GetSchemaTemplatePlan getSchemaTemplatePlan = new GetSchemaTemplatePlan();
+ TemplateInfoResp templateResp =
+ (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan).getDataset();
+ TGetAllTemplatesResp resp = new TGetAllTemplatesResp();
+ resp.setStatus(templateResp.getStatus());
+ if (resp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ if (templateResp.getTemplateList() != null) {
+ List<ByteBuffer> list = new ArrayList<ByteBuffer>();
+ templateResp.getTemplateList().stream()
+ .forEach(
+ item -> {
+ try {
+ list.add(Template.template2ByteBuffer(item));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ resp.setTemplateList(list);
+ }
+ }
+ return resp;
+ }
+
+ /**
+ * show nodes in schema template
+ *
+ * @param req
+ * @return
+ */
+ public TGetTemplateResp getTemplate(String req) {
+ GetNodesInSchemaTemplatePlan getNodesInSchemaTemplatePlan =
+ new GetNodesInSchemaTemplatePlan(req);
+ TemplateInfoResp templateResp =
+ (TemplateInfoResp) getConsensusManager().read(getNodesInSchemaTemplatePlan).getDataset();
+ TGetTemplateResp resp = new TGetTemplateResp();
+ try {
+ if (templateResp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ if (templateResp.getTemplateList() != null && !templateResp.getTemplateList().isEmpty()) {
+ ByteBuffer byteBuffer =
+ Template.template2ByteBuffer(templateResp.getTemplateList().get(0));
+ resp.setTemplate(byteBuffer);
+ }
+ }
+ resp.setStatus(templateResp.getStatus());
+ } catch (IOException e) {
+ resp.setStatus(new TSStatus(TSStatusCode.TEMPLATE_IMCOMPATIBLE.getStatusCode()));
+ }
+ return resp;
+ }
+
private NodeManager getNodeManager() {
return configManager.getNodeManager();
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index c529119ae6..6417569e55 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -48,6 +48,7 @@ import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetSchemaPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.ActivateDataNodePlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.RegisterDataNodePlan;
import org.apache.iotdb.confignode.consensus.request.write.RemoveConfigNodePlan;
import org.apache.iotdb.confignode.consensus.request.write.SetDataReplicationFactorPlan;
@@ -76,8 +77,11 @@ import org.apache.iotdb.confignode.persistence.partition.PartitionInfo;
import org.apache.iotdb.confignode.rpc.thrift.TClusterNodeInfos;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataPartitionResp;
import org.apache.iotdb.confignode.rpc.thrift.TDataPartitionTableResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TPermissionInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TRegionRouteMapResp;
import org.apache.iotdb.confignode.rpc.thrift.TSchemaNodeManagementResp;
@@ -933,4 +937,36 @@ public class ConfigManager implements IManager {
partitionManager.addMetrics();
nodeManager.addMetrics();
}
+
+ @Override
+ public TSStatus createSchemaTemplate(TCreateSchemaTemplateReq req) {
+ TSStatus status = confirmLeader();
+ if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ CreateSchemaTemplatePlan createSchemaTemplatePlan =
+ new CreateSchemaTemplatePlan(req.getSerializedTemplate());
+ return clusterSchemaManager.createTemplate(createSchemaTemplatePlan);
+ } else {
+ return status;
+ }
+ }
+
+ @Override
+ public TGetAllTemplatesResp getAllTemplates() {
+ TSStatus status = confirmLeader();
+ if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ return clusterSchemaManager.getAllTemplates();
+ } else {
+ return new TGetAllTemplatesResp().setStatus(status);
+ }
+ }
+
+ @Override
+ public TGetTemplateResp getTemplate(String req) {
+ TSStatus status = confirmLeader();
+ if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ return clusterSchemaManager.getTemplate(req);
+ } else {
+ return new TGetTemplateResp().setStatus(status);
+ }
+ }
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
index 3c75879daf..5e901f3cf2 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
@@ -41,6 +41,9 @@ import org.apache.iotdb.confignode.manager.load.LoadManager;
import org.apache.iotdb.confignode.rpc.thrift.TClusterNodeInfos;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TPermissionInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TRegionRouteMapResp;
import org.apache.iotdb.confignode.rpc.thrift.TSchemaNodeManagementResp;
@@ -270,4 +273,27 @@ public interface IManager {
/** Show datanodes */
DataSet showDataNodes();
+
+ /**
+ * create schema template
+ *
+ * @param req TCreateSchemaTemplateReq
+ * @return TSStatus
+ */
+ TSStatus createSchemaTemplate(TCreateSchemaTemplateReq req);
+
+ /**
+ * show schema templates
+ *
+ * @return
+ */
+ TGetAllTemplatesResp getAllTemplates();
+
+ /**
+ * show nodes in schema template
+ *
+ * @param req String
+ * @return
+ */
+ TGetTemplateResp getTemplate(String req);
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
index 7053f405a9..6e6b7d604b 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.confignode.consensus.request.read.CountStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.AdjustMaxRegionGroupCountPlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetDataReplicationFactorPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetSchemaReplicationFactorPlan;
@@ -35,9 +36,14 @@ import org.apache.iotdb.confignode.consensus.request.write.SetTTLPlan;
import org.apache.iotdb.confignode.consensus.request.write.SetTimePartitionIntervalPlan;
import org.apache.iotdb.confignode.consensus.response.CountStorageGroupResp;
import org.apache.iotdb.confignode.consensus.response.StorageGroupSchemaResp;
+import org.apache.iotdb.confignode.consensus.response.TemplateInfoResp;
import org.apache.iotdb.confignode.exception.StorageGroupNotExistsException;
+import org.apache.iotdb.confignode.persistence.schema.TemplateTable;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
import org.apache.iotdb.db.metadata.mtree.MTreeAboveSG;
+import org.apache.iotdb.db.metadata.template.Template;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.iotdb.tsfile.utils.Pair;
@@ -50,6 +56,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -73,11 +80,14 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
private final String snapshotFileName = "cluster_schema.bin";
+ private final TemplateTable templateTable;
+
public ClusterSchemaInfo() throws IOException {
storageGroupReadWriteLock = new ReentrantReadWriteLock();
try {
mTree = new MTreeAboveSG();
+ templateTable = new TemplateTable();
} catch (MetadataException e) {
LOGGER.error("Can't construct StorageGroupInfo", e);
throw new IOException(e);
@@ -436,7 +446,11 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
@Override
public boolean processTakeSnapshot(File snapshotDir) throws IOException {
+ processMtreeTakeSnapshot(snapshotDir);
+ return templateTable.processTakeSnapshot(snapshotDir);
+ }
+ public boolean processMtreeTakeSnapshot(File snapshotDir) throws IOException {
File snapshotFile = new File(snapshotDir, snapshotFileName);
if (snapshotFile.exists() && snapshotFile.isFile()) {
LOGGER.error(
@@ -472,7 +486,11 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
@Override
public void processLoadSnapshot(File snapshotDir) throws IOException {
+ processMtreeLoadSnapshot(snapshotDir);
+ templateTable.processLoadSnapshot(snapshotDir);
+ }
+ public void processMtreeLoadSnapshot(File snapshotDir) throws IOException {
File snapshotFile = new File(snapshotDir, snapshotFileName);
if (!snapshotFile.exists() || !snapshotFile.isFile()) {
LOGGER.error(
@@ -534,6 +552,51 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
return matchedNamesInNextLevel;
}
+ public TSStatus createSchemaTemplate(CreateSchemaTemplatePlan createSchemaTemplatePlan) {
+ return templateTable.createTemplate(createSchemaTemplatePlan);
+ }
+
+ public TemplateInfoResp getAllTemplates() {
+ TemplateInfoResp result = new TemplateInfoResp();
+ TGetAllTemplatesResp resp = templateTable.getAllTemplate();
+ result.setStatus(resp.getStatus());
+ if (resp.status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ if (resp.getTemplateList() != null) {
+ List<Template> list = new ArrayList<Template>();
+ resp.getTemplateList().stream()
+ .forEach(
+ item -> {
+ try {
+ list.add(Template.byteBuffer2Template(item));
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException("template deserialization error.", e);
+ }
+ });
+ result.setTemplateList(list);
+ }
+ }
+ return result;
+ }
+
+ public TemplateInfoResp getTemplate(String req) {
+ TemplateInfoResp result = new TemplateInfoResp();
+ TGetTemplateResp resp = templateTable.getMatchedTemplateByName(req);
+ result.setStatus(resp.getStatus());
+ if (resp.status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ if (resp.getTemplate() != null) {
+ List<Template> list = new ArrayList<Template>();
+ try {
+ Template template = Template.byteBuffer2Template(ByteBuffer.wrap(resp.getTemplate()));
+ list.add(template);
+ result.setTemplateList(list);
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException("template deserialization error.", e);
+ }
+ }
+ }
+ return result;
+ }
+
@TestOnly
public void clear() {
mTree.clear();
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
index dc2e5c6e68..2f323911af 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.confignode.consensus.request.read.CountStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataNodeInfoPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetNodePathsPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetNodesInSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetSchemaPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
@@ -38,6 +39,7 @@ import org.apache.iotdb.confignode.consensus.request.write.CreateDataPartitionPl
import org.apache.iotdb.confignode.consensus.request.write.CreateFunctionPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateRegionGroupsPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteProcedurePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.DropFunctionPlan;
@@ -136,6 +138,11 @@ public class ConfigPlanExecutor {
return getSchemaNodeManagementPartition(req);
case GetRegionInfoList:
return partitionInfo.getRegionInfoList((GetRegionInfoListPlan) req);
+ case ShowSchemaTemplate:
+ return clusterSchemaInfo.getAllTemplates();
+ case ShowNodesInSchemaTemplate:
+ GetNodesInSchemaTemplatePlan plan = (GetNodesInSchemaTemplatePlan) req;
+ return clusterSchemaInfo.getTemplate(plan.getTemplateName());
default:
throw new UnknownPhysicalPlanTypeException(req.getType());
}
@@ -199,6 +206,8 @@ public class ConfigPlanExecutor {
return udfInfo.createFunction((CreateFunctionPlan) req);
case DropFunction:
return udfInfo.dropFunction((DropFunctionPlan) req);
+ case CreateSchemaTemplate:
+ return clusterSchemaInfo.createSchemaTemplate((CreateSchemaTemplatePlan) req);
default:
throw new UnknownPhysicalPlanTypeException(req.getType());
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/TemplateTable.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/TemplateTable.java
new file mode 100644
index 0000000000..9b16afb14a
--- /dev/null
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/TemplateTable.java
@@ -0,0 +1,219 @@
+/*
+ * 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.persistence.schema;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.utils.TestOnly;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
+import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class TemplateTable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TemplateTable.class);
+
+ // StorageGroup read write lock
+ private final ReentrantReadWriteLock templateReadWriteLock;
+
+ private final Map<String, Template> templateMap = new ConcurrentHashMap<>();
+
+ private final String snapshotFileName = "template_info.bin";
+
+ public TemplateTable() throws IOException {
+ templateReadWriteLock = new ReentrantReadWriteLock();
+ }
+
+ public TGetTemplateResp getMatchedTemplateByName(String name) {
+ TGetTemplateResp resp = new TGetTemplateResp();
+ try {
+ templateReadWriteLock.readLock().lock();
+ Template template = templateMap.get(name);
+ resp.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+ resp.setTemplate(Template.template2ByteBuffer(template));
+ } catch (IOException e) {
+ LOGGER.warn("Error TemplateInfo name", e);
+ resp.setStatus(new TSStatus(TSStatusCode.TEMPLATE_NOT_EXIST.getStatusCode()));
+ } finally {
+ templateReadWriteLock.readLock().unlock();
+ }
+ return resp;
+ }
+
+ public TGetAllTemplatesResp getAllTemplate() {
+ TGetAllTemplatesResp resp = new TGetAllTemplatesResp();
+ try {
+ templateReadWriteLock.readLock().lock();
+ List<ByteBuffer> templates = new ArrayList<>();
+ this.templateMap.values().stream()
+ .forEach(
+ item -> {
+ try {
+ templates.add(Template.template2ByteBuffer(item));
+ } catch (IOException e) {
+ resp.setStatus(new TSStatus(TSStatusCode.TEMPLATE_IMCOMPATIBLE.getStatusCode()));
+ throw new RuntimeException(e);
+ }
+ });
+ resp.setTemplateList(templates);
+ resp.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+ } catch (RuntimeException e) {
+ LOGGER.warn("Error TemplateInfo name", e);
+ resp.setStatus(new TSStatus(TSStatusCode.TEMPLATE_IMCOMPATIBLE.getStatusCode()));
+ } finally {
+ templateReadWriteLock.readLock().unlock();
+ }
+ return resp;
+ }
+
+ public TSStatus createTemplate(CreateSchemaTemplatePlan createSchemaTemplatePlan) {
+ try {
+ templateReadWriteLock.readLock().lock();
+ Template template =
+ Template.byteBuffer2Template(ByteBuffer.wrap(createSchemaTemplatePlan.getTemplate()));
+ Template temp = this.templateMap.get(template.getName());
+ if (temp != null && template.getName().equalsIgnoreCase(temp.getName())) {
+ LOGGER.error(
+ "Failed to create template, because template name {} is exists", template.getName());
+ return new TSStatus(TSStatusCode.DUPLICATED_TEMPLATE.getStatusCode());
+ }
+ this.templateMap.put(template.getName(), template);
+ return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+ } catch (IOException | ClassNotFoundException e) {
+ LOGGER.warn("Error to create template", e);
+ return new TSStatus(TSStatusCode.CREATE_TEMPLATE_ERROR.getStatusCode());
+ } finally {
+ templateReadWriteLock.readLock().unlock();
+ }
+ }
+
+ private void serialize(OutputStream outputStream) throws IOException {
+ ReadWriteIOUtils.write(templateMap.size(), outputStream);
+ for (Map.Entry<String, Template> entry : templateMap.entrySet()) {
+ serializeTemplate(entry.getValue(), outputStream);
+ }
+ }
+
+ private void serializeTemplate(Template template, OutputStream outputStream) {
+ try {
+ ByteBuffer dataBuffer = template.serialize();
+ ReadWriteIOUtils.write(dataBuffer, outputStream);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void deserialize(InputStream inputStream) throws IOException {
+ ByteBuffer byteBuffer = ByteBuffer.wrap(IOUtils.toByteArray(inputStream));
+ int size = ReadWriteIOUtils.readInt(byteBuffer);
+ while (size > 0) {
+ Template template = deserializeTemplate(byteBuffer);
+ templateMap.put(template.getName(), template);
+ size--;
+ }
+ }
+
+ private Template deserializeTemplate(ByteBuffer byteBuffer) {
+ Template template = new Template();
+ int length = ReadWriteIOUtils.readInt(byteBuffer);
+ byte[] data = ReadWriteIOUtils.readBytes(byteBuffer, length);
+ template.deserialize(ByteBuffer.wrap(data));
+ return template;
+ }
+
+ public boolean processTakeSnapshot(File snapshotDir) throws IOException {
+ File snapshotFile = new File(snapshotDir, snapshotFileName);
+ if (snapshotFile.exists() && snapshotFile.isFile()) {
+ LOGGER.error(
+ "template failed to take snapshot, because snapshot file [{}] is already exist.",
+ snapshotFile.getAbsolutePath());
+ return false;
+ }
+ File tmpFile = new File(snapshotFile.getAbsolutePath() + "-" + UUID.randomUUID());
+ templateReadWriteLock.writeLock().lock();
+ try (FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
+ BufferedOutputStream outputStream = new BufferedOutputStream(fileOutputStream)) {
+ serialize(outputStream);
+ outputStream.flush();
+ fileOutputStream.flush();
+ outputStream.close();
+ fileOutputStream.close();
+ return tmpFile.renameTo(snapshotFile);
+ } finally {
+ for (int retry = 0; retry < 5; retry++) {
+ if (!tmpFile.exists() || tmpFile.delete()) {
+ break;
+ } else {
+ LOGGER.warn(
+ "Can't delete temporary snapshot file: {}, retrying...", tmpFile.getAbsolutePath());
+ }
+ }
+ templateReadWriteLock.writeLock().unlock();
+ }
+ }
+
+ public void processLoadSnapshot(File snapshotDir) throws IOException {
+ File snapshotFile = new File(snapshotDir, snapshotFileName);
+ if (!snapshotFile.exists() || !snapshotFile.isFile()) {
+ LOGGER.error(
+ "Failed to load snapshot,snapshot file [{}] is not exist.",
+ snapshotFile.getAbsolutePath());
+ return;
+ }
+ templateReadWriteLock.writeLock().lock();
+ try (FileInputStream fileInputStream = new FileInputStream(snapshotFile);
+ BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)) {
+ // Load snapshot of template
+ this.templateMap.clear();
+ deserialize(bufferedInputStream);
+ bufferedInputStream.close();
+ fileInputStream.close();
+ } finally {
+ templateReadWriteLock.writeLock().unlock();
+ }
+ }
+
+ @TestOnly
+ public void clear() {
+ this.templateMap.clear();
+ }
+}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index c797ede063..8667f80c40 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -65,6 +65,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterResp;
import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
import org.apache.iotdb.confignode.rpc.thrift.TCreateFunctionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeActiveReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -75,6 +76,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TDataPartitionTableResp;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteStorageGroupReq;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteStorageGroupsReq;
import org.apache.iotdb.confignode.rpc.thrift.TDropFunctionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TLoginReq;
import org.apache.iotdb.confignode.rpc.thrift.TPermissionInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TRegionRouteMapResp;
@@ -527,4 +530,19 @@ public class ConfigNodeRPCServiceProcessor implements IConfigNodeRPCService.Ifac
public void handleClientExit() {}
// TODO: Interfaces for data operations
+
+ @Override
+ public TSStatus createSchemaTemplate(TCreateSchemaTemplateReq req) throws TException {
+ return configManager.createSchemaTemplate(req);
+ }
+
+ @Override
+ public TGetAllTemplatesResp getAllTemplates() throws TException {
+ return configManager.getAllTemplates();
+ }
+
+ @Override
+ public TGetTemplateResp getTemplate(String req) throws TException {
+ return configManager.getTemplate(req);
+ }
}
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
index 3c5859e674..8f35519eb4 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
import org.apache.iotdb.commons.auth.AuthException;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
+import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.partition.DataPartitionTable;
import org.apache.iotdb.commons.partition.SchemaPartitionTable;
import org.apache.iotdb.commons.partition.SeriesPartitionTable;
@@ -36,10 +37,12 @@ import org.apache.iotdb.confignode.consensus.request.auth.AuthorPlan;
import org.apache.iotdb.confignode.consensus.request.read.CountStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataNodeInfoPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetDataPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetNodesInSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetOrCreateDataPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetOrCreateSchemaPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
import org.apache.iotdb.confignode.consensus.request.read.GetSchemaPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.read.GetSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.read.GetStorageGroupPlan;
import org.apache.iotdb.confignode.consensus.request.write.ActivateDataNodePlan;
import org.apache.iotdb.confignode.consensus.request.write.AdjustMaxRegionGroupCountPlan;
@@ -47,6 +50,7 @@ import org.apache.iotdb.confignode.consensus.request.write.ApplyConfigNodePlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateDataPartitionPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateRegionGroupsPlan;
import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaPartitionPlan;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteProcedurePlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteRegionsPlan;
import org.apache.iotdb.confignode.consensus.request.write.DeleteStorageGroupPlan;
@@ -61,6 +65,11 @@ import org.apache.iotdb.confignode.consensus.request.write.UpdateProcedurePlan;
import org.apache.iotdb.confignode.procedure.Procedure;
import org.apache.iotdb.confignode.procedure.impl.DeleteStorageGroupProcedure;
import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
+import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.utils.Pair;
import org.junit.Assert;
@@ -593,4 +602,50 @@ public class ConfigPhysicalPlanSerDeTest {
Assert.assertEquals(req0.getType(), req1.getType());
Assert.assertEquals(req0.getRegionType(), req1.getRegionType());
}
+
+ @Test
+ public void CreateSchemaTemplatePlanTest() throws IOException, IllegalPathException {
+ Template template = new Template(newCreateSchemaTemplateStatement("template_name"));
+ CreateSchemaTemplatePlan createSchemaTemplatePlan0 =
+ new CreateSchemaTemplatePlan(Template.template2ByteBuffer(template).array());
+ CreateSchemaTemplatePlan createSchemaTemplatePlan1 =
+ (CreateSchemaTemplatePlan)
+ ConfigPhysicalPlan.Factory.create(createSchemaTemplatePlan0.serializeToByteBuffer());
+ Assert.assertEquals(createSchemaTemplatePlan0, createSchemaTemplatePlan1);
+ }
+
+ private CreateSchemaTemplateStatement newCreateSchemaTemplateStatement(String name) {
+ List<List<String>> measurements =
+ Arrays.asList(
+ Arrays.asList(name + "_" + "temperature"), Arrays.asList(name + "_" + "status"));
+ List<List<TSDataType>> dataTypes =
+ Arrays.asList(Arrays.asList(TSDataType.FLOAT), Arrays.asList(TSDataType.BOOLEAN));
+ List<List<TSEncoding>> encodings =
+ Arrays.asList(Arrays.asList(TSEncoding.RLE), Arrays.asList(TSEncoding.PLAIN));
+ List<List<CompressionType>> compressors =
+ Arrays.asList(Arrays.asList(CompressionType.SNAPPY), Arrays.asList(CompressionType.SNAPPY));
+ CreateSchemaTemplateStatement createSchemaTemplateStatement =
+ new CreateSchemaTemplateStatement(name, measurements, dataTypes, encodings, compressors);
+ return createSchemaTemplateStatement;
+ }
+
+ @Test
+ public void GetSchemaTemplatePlanTest() throws IOException {
+ GetSchemaTemplatePlan getSchemaTemplatePlan0 = new GetSchemaTemplatePlan();
+ GetSchemaTemplatePlan getSchemaTemplatePlan1 =
+ (GetSchemaTemplatePlan)
+ ConfigPhysicalPlan.Factory.create(getSchemaTemplatePlan0.serializeToByteBuffer());
+ Assert.assertEquals(getSchemaTemplatePlan0, getSchemaTemplatePlan1);
+ }
+
+ @Test
+ public void GetNodesInSchemaTemplatePlanTest() throws IOException {
+ GetNodesInSchemaTemplatePlan getNodesInSchemaTemplatePlan0 =
+ new GetNodesInSchemaTemplatePlan("template_name_test");
+ GetNodesInSchemaTemplatePlan getNodesInSchemaTemplatePlan1 =
+ (GetNodesInSchemaTemplatePlan)
+ ConfigPhysicalPlan.Factory.create(
+ getNodesInSchemaTemplatePlan0.serializeToByteBuffer());
+ Assert.assertEquals(getNodesInSchemaTemplatePlan0, getNodesInSchemaTemplatePlan1);
+ }
}
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java
new file mode 100644
index 0000000000..944060d30b
--- /dev/null
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.persistence;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaTemplatePlan;
+import org.apache.iotdb.confignode.persistence.schema.TemplateTable;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
+import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.thrift.TException;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.apache.iotdb.db.constant.TestConstant.BASE_OUTPUT_PATH;
+
+public class TemplateTableTest {
+
+ private static TemplateTable templateTable;
+ private static final File snapshotDir = new File(BASE_OUTPUT_PATH, "snapshot");
+
+ @BeforeClass
+ public static void setup() throws IOException {
+ templateTable = new TemplateTable();
+ if (!snapshotDir.exists()) {
+ snapshotDir.mkdirs();
+ }
+ }
+
+ @AfterClass
+ public static void cleanup() throws IOException {
+ templateTable.clear();
+ if (snapshotDir.exists()) {
+ FileUtils.deleteDirectory(snapshotDir);
+ }
+ }
+
+ @Test
+ public void testSnapshot()
+ throws IOException, TException, IllegalPathException, ClassNotFoundException {
+ int n = 2;
+ String templateName = "template_test";
+
+ List<Template> templates = new ArrayList<>();
+ // create schema template
+ for (int i = 0; i < n; i++) {
+ String templateNameTmp = templateName + "_" + i;
+ CreateSchemaTemplateStatement statement = null;
+ if (i == 1) {
+ statement = newCreateSchemaTemplateStatementAlign(templateNameTmp);
+ } else {
+ statement = newCreateSchemaTemplateStatement(templateNameTmp);
+ }
+ Template template = new Template(statement);
+ templates.add(template);
+ CreateSchemaTemplatePlan createSchemaTemplatePlan =
+ new CreateSchemaTemplatePlan(Template.template2ByteBuffer(template).array());
+ templateTable.createTemplate(createSchemaTemplatePlan);
+ }
+
+ templateTable.processTakeSnapshot(snapshotDir);
+ templateTable.clear();
+ templateTable.processLoadSnapshot(snapshotDir);
+
+ // show nodes in schema template
+ for (int i = 0; i < n; i++) {
+ String templateNameTmp = templateName + "_" + i;
+ TGetTemplateResp templateResp = templateTable.getMatchedTemplateByName(templateNameTmp);
+ Template template = templates.get(i);
+ Template serTemplate =
+ Template.byteBuffer2Template(ByteBuffer.wrap(templateResp.getTemplate()));
+ Assert.assertEquals(template, serTemplate);
+ }
+ }
+
+ private CreateSchemaTemplateStatement newCreateSchemaTemplateStatement(String name) {
+ List<List<String>> measurements =
+ Arrays.asList(
+ Arrays.asList(name + "_" + "temperature"), Arrays.asList(name + "_" + "status"));
+ List<List<TSDataType>> dataTypes =
+ Arrays.asList(Arrays.asList(TSDataType.FLOAT), Arrays.asList(TSDataType.BOOLEAN));
+ List<List<TSEncoding>> encodings =
+ Arrays.asList(Arrays.asList(TSEncoding.RLE), Arrays.asList(TSEncoding.PLAIN));
+ List<List<CompressionType>> compressors =
+ Arrays.asList(Arrays.asList(CompressionType.SNAPPY), Arrays.asList(CompressionType.SNAPPY));
+ CreateSchemaTemplateStatement createSchemaTemplateStatement =
+ new CreateSchemaTemplateStatement(name, measurements, dataTypes, encodings, compressors);
+ return createSchemaTemplateStatement;
+ }
+
+ private CreateSchemaTemplateStatement newCreateSchemaTemplateStatementAlign(String name) {
+ List<List<String>> measurements =
+ Arrays.asList(Arrays.asList(name + "_" + "lat", name + "_" + "lon"));
+ List<List<TSDataType>> dataTypes =
+ Arrays.asList(Arrays.asList(TSDataType.FLOAT, TSDataType.FLOAT));
+ List<List<TSEncoding>> encodings =
+ Arrays.asList(Arrays.asList(TSEncoding.GORILLA, TSEncoding.GORILLA));
+ List<List<CompressionType>> compressors =
+ Arrays.asList(Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
+ CreateSchemaTemplateStatement createSchemaTemplateStatement =
+ new CreateSchemaTemplateStatement(name, measurements, dataTypes, encodings, compressors);
+ return createSchemaTemplateStatement;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
index 61aa287bd5..f3d722af16 100644
--- a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
+++ b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
@@ -40,6 +40,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterResp;
import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
import org.apache.iotdb.confignode.rpc.thrift.TCreateFunctionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeActiveReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -50,6 +51,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TDataPartitionTableResp;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteStorageGroupReq;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteStorageGroupsReq;
import org.apache.iotdb.confignode.rpc.thrift.TDropFunctionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TLoginReq;
import org.apache.iotdb.confignode.rpc.thrift.TPermissionInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TRegionRouteMapResp;
@@ -804,6 +807,54 @@ public class ConfigNodeClient
throw new TException(MSG_RECONNECTION_FAIL);
}
+ @Override
+ public TSStatus createSchemaTemplate(TCreateSchemaTemplateReq req) throws TException {
+ for (int i = 0; i < RETRY_NUM; i++) {
+ try {
+ TSStatus tsStatus = client.createSchemaTemplate(req);
+ if (!updateConfigNodeLeader(tsStatus)) {
+ return tsStatus;
+ }
+ } catch (TException e) {
+ configLeader = null;
+ }
+ reconnect();
+ }
+ throw new TException(MSG_RECONNECTION_FAIL);
+ }
+
+ @Override
+ public TGetAllTemplatesResp getAllTemplates() throws TException {
+ for (int i = 0; i < RETRY_NUM; i++) {
+ try {
+ TGetAllTemplatesResp resp = client.getAllTemplates();
+ if (!updateConfigNodeLeader(resp.getStatus())) {
+ return resp;
+ }
+ } catch (TException e) {
+ configLeader = null;
+ }
+ reconnect();
+ }
+ throw new TException(MSG_RECONNECTION_FAIL);
+ }
+
+ @Override
+ public TGetTemplateResp getTemplate(String req) throws TException {
+ for (int i = 0; i < RETRY_NUM; i++) {
+ try {
+ TGetTemplateResp resp = client.getTemplate(req);
+ if (!updateConfigNodeLeader(resp.getStatus())) {
+ return resp;
+ }
+ } catch (TException e) {
+ configLeader = null;
+ }
+ reconnect();
+ }
+ throw new TException(MSG_RECONNECTION_FAIL);
+ }
+
public static class Factory extends BaseClientFactory<PartitionRegionId, ConfigNodeClient> {
public Factory(
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
new file mode 100644
index 0000000000..08beb9ef48
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
@@ -0,0 +1,161 @@
+/*
+ * 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.metadata.template;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.client.IClientManager;
+import org.apache.iotdb.commons.consensus.PartitionRegionId;
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
+import org.apache.iotdb.db.client.ConfigNodeClient;
+import org.apache.iotdb.db.client.ConfigNodeInfo;
+import org.apache.iotdb.db.client.DataNodeClientPoolFactory;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.apache.thrift.TException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class ClusterTemplateManager implements ITemplateManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClusterTemplateManager.class);
+
+ private static final class ClusterTemplateManagerHolder {
+ private static final ClusterTemplateManager INSTANCE = new ClusterTemplateManager();
+
+ private ClusterTemplateManagerHolder() {}
+ }
+
+ public static ClusterTemplateManager getInstance() {
+ return ClusterTemplateManager.ClusterTemplateManagerHolder.INSTANCE;
+ }
+
+ private static final IClientManager<PartitionRegionId, ConfigNodeClient>
+ CONFIG_NODE_CLIENT_MANAGER =
+ new IClientManager.Factory<PartitionRegionId, ConfigNodeClient>()
+ .createClientManager(new DataNodeClientPoolFactory.ConfigNodeClientPoolFactory());
+
+ @Override
+ public TSStatus createSchemaTemplate(CreateSchemaTemplateStatement statement) {
+ TCreateSchemaTemplateReq req = constructTCreateSchemaTemplateReq(statement);
+ try (ConfigNodeClient configNodeClient =
+ CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
+ // Send request to some API server
+ TSStatus tsStatus = configNodeClient.createSchemaTemplate(req);
+ // Get response or throw exception
+ if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != tsStatus.getCode()) {
+ LOGGER.error(
+ "Failed to execute create schema template {} in config node, status is {}.",
+ statement.getName(),
+ tsStatus);
+ }
+ return tsStatus;
+ } catch (TException | IOException e) {
+ throw new RuntimeException(
+ new IoTDBException(
+ "create template error.", e, TSStatusCode.CREATE_TEMPLATE_ERROR.getStatusCode()));
+ }
+ }
+
+ private TCreateSchemaTemplateReq constructTCreateSchemaTemplateReq(
+ CreateSchemaTemplateStatement statement) {
+ TCreateSchemaTemplateReq req = new TCreateSchemaTemplateReq();
+ try {
+ Template template = new Template(statement);
+ req.setName(template.getName());
+ req.setSerializedTemplate(Template.template2ByteBuffer(template));
+ } catch (IOException | IllegalPathException e) {
+ throw new RuntimeException(e);
+ }
+ return req;
+ }
+
+ @Override
+ public List<Template> getAllTemplates() {
+ List<Template> templatesList = new ArrayList<>();
+ try (ConfigNodeClient configNodeClient =
+ CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
+ TGetAllTemplatesResp tGetAllTemplatesResp = configNodeClient.getAllTemplates();
+ // Get response or throw exception
+ if (tGetAllTemplatesResp.getStatus().getCode()
+ == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ List<ByteBuffer> list = tGetAllTemplatesResp.getTemplateList();
+ Optional<List<ByteBuffer>> optional = Optional.ofNullable(list);
+ optional.orElse(new ArrayList<>()).stream()
+ .forEach(
+ item -> {
+ try {
+ Template template = Template.byteBuffer2Template(item);
+ templatesList.add(template);
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException(
+ new IoTDBException(
+ "deserialize template error.",
+ e,
+ TSStatusCode.TEMPLATE_IMCOMPATIBLE.getStatusCode()));
+ }
+ });
+ } else {
+ throw new RuntimeException(
+ new IoTDBException(
+ tGetAllTemplatesResp.getStatus().getMessage(),
+ tGetAllTemplatesResp.getStatus().getCode()));
+ }
+ } catch (TException | IOException e) {
+ throw new RuntimeException(
+ new IoTDBException(
+ "get all template error.", TSStatusCode.UNDEFINED_TEMPLATE.getStatusCode()));
+ }
+ return templatesList;
+ }
+
+ @Override
+ public Template getTemplate(String name) {
+ Template template = null;
+ try (ConfigNodeClient configNodeClient =
+ CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
+ TGetTemplateResp resp = configNodeClient.getTemplate(name);
+ if (resp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ byte[] templateBytes = resp.getTemplate();
+ if (templateBytes != null && templateBytes.length > 0) {
+ template = Template.byteBuffer2Template(ByteBuffer.wrap(templateBytes));
+ }
+ } else {
+ throw new RuntimeException(
+ new IoTDBException(resp.status.getMessage(), resp.status.getCode()));
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(
+ new IoTDBException(
+ "get template info error.", TSStatusCode.UNDEFINED_TEMPLATE.getStatusCode()));
+ }
+ return template;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/ITemplateManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/ITemplateManager.java
new file mode 100644
index 0000000000..d2abfe8eeb
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/ITemplateManager.java
@@ -0,0 +1,49 @@
+/*
+ * 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.metadata.template;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+
+import java.util.List;
+
+public interface ITemplateManager {
+
+ /**
+ * @param statement CreateSchemaTemplateStatement
+ * @return TSStatus
+ */
+ TSStatus createSchemaTemplate(CreateSchemaTemplateStatement statement);
+
+ /**
+ * show schema templates
+ *
+ * @return List<Template>
+ */
+ List<Template> getAllTemplates();
+
+ /**
+ * show nodes in schema template xx
+ *
+ * @param name
+ * @return Template
+ */
+ Template getTemplate(String name);
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
index 68f01446bb..ba5928bbcd 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
@@ -30,6 +30,7 @@ import org.apache.iotdb.db.metadata.mnode.IEntityMNode;
import org.apache.iotdb.db.metadata.mnode.IMNode;
import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
import org.apache.iotdb.db.qp.physical.sys.CreateTemplatePlan;
import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -42,9 +43,13 @@ import org.apache.iotdb.tsfile.write.schema.VectorMeasurementSchema;
import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -59,7 +64,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-public class Template {
+public class Template implements Serializable {
private String name;
private Map<String, IMNode> directNodes;
private boolean isDirectAligned;
@@ -137,6 +142,21 @@ public class Template {
}
}
+ /**
+ * build a template from a CreateSchemaTemplateStatement
+ *
+ * @param statement CreateSchemaTemplateStatement
+ */
+ public Template(CreateSchemaTemplateStatement statement) throws IllegalPathException {
+ this(
+ new CreateTemplatePlan(
+ statement.getName(),
+ statement.getMeasurements(),
+ statement.getDataTypes(),
+ statement.getEncodings(),
+ statement.getCompressors()));
+ }
+
public String getName() {
return name;
}
@@ -713,4 +733,19 @@ public class Template {
public void setRehash(int code) {
rehashCode = code;
}
+
+ public static ByteBuffer template2ByteBuffer(Template template) throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream dataOutputStream = new ObjectOutputStream(byteArrayOutputStream);
+ dataOutputStream.writeObject(template);
+ return ByteBuffer.wrap(byteArrayOutputStream.toByteArray());
+ }
+
+ public static Template byteBuffer2Template(ByteBuffer byteBuffer)
+ throws IOException, ClassNotFoundException {
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteBuffer.array());
+ ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
+ Template template = (Template) ois.readObject();
+ return template;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/HeaderConstant.java b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/HeaderConstant.java
index 4fb07662ab..616072b1a0 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/HeaderConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/HeaderConstant.java
@@ -81,6 +81,9 @@ public class HeaderConstant {
public static final String COLUMN_DATA_REGION_NUM = "DataRegionNum";
public static final String COLUMN_SCHEMA_REGION_NUM = "SchemaRegionNum";
+ // column names for show schema template statement
+ public static final String COLUMN_TEMPLATE_NAME = "template name";
+
// dataset header for schema statement
public static final DatasetHeader showTimeSeriesHeader;
public static final DatasetHeader showDevicesHeader;
@@ -113,6 +116,12 @@ public class HeaderConstant {
// dataset header for show datanodes
public static final DatasetHeader showDataNodesHeader;
+ // dataset header for show nodes in schema template
+ public static final DatasetHeader showNodesInSchemaTemplate;
+
+ // dataset header for show schma template
+ public static final DatasetHeader showSchemaTemplate;
+
static {
countStorageGroupHeader =
new DatasetHeader(
@@ -251,4 +260,18 @@ public class HeaderConstant {
new ColumnHeader(COLUMN_SCHEMA_REGION_NUM, TSDataType.INT32)),
true);
}
+
+ static {
+ showSchemaTemplate =
+ new DatasetHeader(
+ Arrays.asList(new ColumnHeader(COLUMN_TEMPLATE_NAME, TSDataType.TEXT)), true);
+ showNodesInSchemaTemplate =
+ new DatasetHeader(
+ Arrays.asList(
+ new ColumnHeader(COLUMN_CHILDNODES, TSDataType.TEXT),
+ new ColumnHeader(COLUMN_TIMESERIES_DATATYPE, TSDataType.TEXT),
+ new ColumnHeader(COLUMN_TIMESERIES_ENCODING, TSDataType.TEXT),
+ new ColumnHeader(COLUMN_TIMESERIES_COMPRESSION, TSDataType.TEXT)),
+ true);
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
index 8a9a063865..ccbe7a1b11 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
@@ -79,6 +79,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -1433,6 +1436,43 @@ public class Analyzer {
return analysis;
}
+
+ @Override
+ public Analysis visitCreateSchemaTemplate(
+ CreateSchemaTemplateStatement createTemplateStatement, MPPQueryContext context) {
+
+ context.setQueryType(QueryType.WRITE);
+ List<List<String>> measurementsList = createTemplateStatement.getMeasurements();
+ for (List measurements : measurementsList) {
+ Set<String> measurementsSet = new HashSet<>(measurements);
+ if (measurementsSet.size() < measurements.size()) {
+ throw new SemanticException(
+ "Measurement under an aligned device is not allowed to have the same measurement name");
+ }
+ }
+ Analysis analysis = new Analysis();
+ analysis.setStatement(createTemplateStatement);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement,
+ MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showNodesInSchemaTemplateStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showNodesInSchemaTemplate);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showSchemaTemplateStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showSchemaTemplate);
+ return analysis;
+ }
}
private GroupByFilter initGroupByFilter(GroupByTimeComponent groupByTimeComponent) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/constant/StatementType.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/constant/StatementType.java
index c4e14cc331..cd94366880 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/constant/StatementType.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/constant/StatementType.java
@@ -129,6 +129,8 @@ public enum StatementType {
PRUNE_TEMPLATE,
APPEND_TEMPLATE,
DROP_TEMPLATE,
+ SHOW_SCHEMA_TEMPLATE,
+ SHOW_NODES_IN_SCHEMA_TEMPLATE,
SHOW_QUERY_RESOURCE,
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ConfigTaskVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ConfigTaskVisitor.java
index fd4da7abbc..0b1f6107fa 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ConfigTaskVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ConfigTaskVisitor.java
@@ -35,6 +35,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowRegionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.UnSetTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.FlushStatement;
import org.apache.iotdb.tsfile.exception.NotImplementedException;
@@ -130,6 +133,24 @@ public class ConfigTaskVisitor
return new ShowRegionTask(showRegionStatement);
}
+ @Override
+ public IConfigTask visitCreateSchemaTemplate(
+ CreateSchemaTemplateStatement createSchemaTemplateStatement, TaskContext context) {
+ return new CreateSchemaTemplateTask(createSchemaTemplateStatement);
+ }
+
+ @Override
+ public IConfigTask visitShowNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement, TaskContext context) {
+ return new ShowNodesInSchemaTemplateTask(showNodesInSchemaTemplateStatement);
+ }
+
+ @Override
+ public IConfigTask visitShowSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement, TaskContext context) {
+ return new ShowSchemaTemplateTask(showSchemaTemplateStatement);
+ }
+
@Override
public IConfigTask visitShowDataNodes(
ShowDataNodesStatement showDataNodesStatement, TaskContext context) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/CreateSchemaTemplateTask.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/CreateSchemaTemplateTask.java
new file mode 100644
index 0000000000..231f7de5e9
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/CreateSchemaTemplateTask.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mpp.plan.execution.config;
+
+import org.apache.iotdb.db.mpp.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class CreateSchemaTemplateTask implements IConfigTask {
+
+ private final CreateSchemaTemplateStatement createSchemaTemplateStatement;
+
+ public CreateSchemaTemplateTask(CreateSchemaTemplateStatement createSchemaTemplateStatement) {
+ this.createSchemaTemplateStatement = createSchemaTemplateStatement;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(IConfigTaskExecutor configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.createSchemaTemplate(this.createSchemaTemplateStatement);
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowNodesInSchemaTemplateTask.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowNodesInSchemaTemplateTask.java
new file mode 100644
index 0000000000..7faaec9372
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowNodesInSchemaTemplateTask.java
@@ -0,0 +1,79 @@
+/*
+ * 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.mpp.plan.execution.config;
+
+import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
+import org.apache.iotdb.db.mpp.common.header.HeaderConstant;
+import org.apache.iotdb.db.mpp.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.iotdb.tsfile.utils.Binary;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.Map;
+
+public class ShowNodesInSchemaTemplateTask implements IConfigTask {
+
+ private final ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement;
+
+ public ShowNodesInSchemaTemplateTask(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement) {
+ this.showNodesInSchemaTemplateStatement = showNodesInSchemaTemplateStatement;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(IConfigTaskExecutor configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showNodesInSchemaTemplate(this.showNodesInSchemaTemplateStatement);
+ }
+
+ public static void buildTSBlock(Template template, SettableFuture<ConfigTaskResult> future) {
+ TsBlockBuilder builder =
+ new TsBlockBuilder(HeaderConstant.showNodesInSchemaTemplate.getRespDataTypes());
+ try {
+ if (template != null) {
+ // template.get
+ for (Map.Entry<String, IMeasurementSchema> entry : template.getSchemaMap().entrySet()) {
+ String keyName = entry.getKey();
+ IMeasurementSchema measurementSchema = entry.getValue();
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder.getColumnBuilder(0).writeBinary(new Binary(keyName));
+ builder.getColumnBuilder(1).writeBinary(new Binary(measurementSchema.getType().name()));
+ builder
+ .getColumnBuilder(2)
+ .writeBinary(new Binary(measurementSchema.getEncodingType().name()));
+ builder
+ .getColumnBuilder(3)
+ .writeBinary(new Binary(measurementSchema.getCompressor().name()));
+ builder.declarePosition();
+ }
+ }
+ } catch (Exception e) {
+
+ }
+ DatasetHeader datasetHeader = HeaderConstant.showNodesInSchemaTemplate;
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS, builder.build(), datasetHeader));
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowSchemaTemplateTask.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowSchemaTemplateTask.java
new file mode 100644
index 0000000000..9ceca337a9
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/ShowSchemaTemplateTask.java
@@ -0,0 +1,67 @@
+/*
+ * 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.mpp.plan.execution.config;
+
+import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
+import org.apache.iotdb.db.mpp.common.header.HeaderConstant;
+import org.apache.iotdb.db.mpp.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.iotdb.tsfile.utils.Binary;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class ShowSchemaTemplateTask implements IConfigTask {
+
+ private final ShowSchemaTemplateStatement showSchemaTemplateStatement;
+
+ public ShowSchemaTemplateTask(ShowSchemaTemplateStatement showSchemaTemplateStatement) {
+ this.showSchemaTemplateStatement = showSchemaTemplateStatement;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(IConfigTaskExecutor configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showSchemaTemplate(this.showSchemaTemplateStatement);
+ }
+
+ public static void buildTSBlock(
+ List<Template> templateList, SettableFuture<ConfigTaskResult> future) {
+ TsBlockBuilder builder =
+ new TsBlockBuilder(HeaderConstant.showSchemaTemplate.getRespDataTypes());
+ Optional<List<Template>> optional = Optional.ofNullable(templateList);
+ optional.orElse(new ArrayList<>()).stream()
+ .forEach(
+ template -> {
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder.getColumnBuilder(0).writeBinary(new Binary(template.getName()));
+ builder.declarePosition();
+ });
+ DatasetHeader datasetHeader = HeaderConstant.showSchemaTemplate;
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS, builder.build(), datasetHeader));
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 7f5a0d51ab..0d04cf2792 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
import org.apache.iotdb.confignode.rpc.thrift.TCreateFunctionReq;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteStorageGroupsReq;
import org.apache.iotdb.confignode.rpc.thrift.TDropFunctionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
import org.apache.iotdb.confignode.rpc.thrift.TSetStorageGroupReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowDataNodesResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
@@ -40,12 +41,16 @@ import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchemaResp;
import org.apache.iotdb.db.client.ConfigNodeClient;
import org.apache.iotdb.db.client.ConfigNodeInfo;
import org.apache.iotdb.db.client.DataNodeClientPoolFactory;
+import org.apache.iotdb.db.metadata.template.ClusterTemplateManager;
+import org.apache.iotdb.db.metadata.template.Template;
import org.apache.iotdb.db.mpp.plan.execution.config.ConfigTaskResult;
import org.apache.iotdb.db.mpp.plan.execution.config.CountStorageGroupTask;
import org.apache.iotdb.db.mpp.plan.execution.config.SetStorageGroupTask;
import org.apache.iotdb.db.mpp.plan.execution.config.ShowClusterTask;
import org.apache.iotdb.db.mpp.plan.execution.config.ShowDataNodesTask;
+import org.apache.iotdb.db.mpp.plan.execution.config.ShowNodesInSchemaTemplateTask;
import org.apache.iotdb.db.mpp.plan.execution.config.ShowRegionTask;
+import org.apache.iotdb.db.mpp.plan.execution.config.ShowSchemaTemplateTask;
import org.apache.iotdb.db.mpp.plan.execution.config.ShowStorageGroupTask;
import org.apache.iotdb.db.mpp.plan.execution.config.ShowTTLTask;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountStorageGroupStatement;
@@ -56,6 +61,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDataNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowRegionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.rpc.TSStatusCode;
@@ -364,4 +372,63 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
ShowDataNodesTask.buildTSBlock(showDataNodesResp, future);
return future;
}
+
+ @Override
+ public SettableFuture<ConfigTaskResult> createSchemaTemplate(
+ CreateSchemaTemplateStatement createSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ // Construct request using statement
+ try {
+ // Send request to some API server
+ TSStatus tsStatus =
+ ClusterTemplateManager.getInstance().createSchemaTemplate(createSchemaTemplateStatement);
+ // Get response or throw exception
+ if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != tsStatus.getCode()) {
+ LOGGER.error(
+ "Failed to execute create schema template {} in config node, status is {}.",
+ createSchemaTemplateStatement.getName(),
+ tsStatus);
+ future.setException(new StatementExecutionException(tsStatus));
+ } else {
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
+ }
+ } catch (Exception e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
+ @Override
+ public SettableFuture<ConfigTaskResult> showSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ try (ConfigNodeClient configNodeClient =
+ CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
+ // Send request to some API server
+ List<Template> templateList = ClusterTemplateManager.getInstance().getAllTemplates();
+ // build TSBlock
+ ShowSchemaTemplateTask.buildTSBlock(templateList, future);
+ } catch (Exception e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
+ @Override
+ public SettableFuture<ConfigTaskResult> showNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ String req = showNodesInSchemaTemplateStatement.getTemplateName();
+ TGetTemplateResp tGetTemplateResp = new TGetTemplateResp();
+ try (ConfigNodeClient configNodeClient =
+ CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
+ // Send request to some API server
+ Template template = ClusterTemplateManager.getInstance().getTemplate(req);
+ // build TSBlock
+ ShowNodesInSchemaTemplateTask.buildTSBlock(template, future);
+ } catch (Exception e) {
+ future.setException(e);
+ }
+ return future;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/IConfigTaskExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/IConfigTaskExecutor.java
index 2eadef660c..ed2eba46a5 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/IConfigTaskExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -29,6 +29,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDataNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowRegionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import com.google.common.util.concurrent.SettableFuture;
@@ -64,4 +67,13 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showRegion(ShowRegionStatement showRegionStatement);
SettableFuture<ConfigTaskResult> showDataNodes(ShowDataNodesStatement showDataNodesStatement);
+
+ SettableFuture<ConfigTaskResult> createSchemaTemplate(
+ CreateSchemaTemplateStatement createSchemaTemplateStatement);
+
+ SettableFuture<ConfigTaskResult> showSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement);
+
+ SettableFuture<ConfigTaskResult> showNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement);
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/StandaloneConfigTaskExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/StandaloneConfigTaskExecutor.java
index c23fef90af..e4badb3c1a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/StandaloneConfigTaskExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/StandaloneConfigTaskExecutor.java
@@ -41,6 +41,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDataNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowRegionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.rpc.TSStatusCode;
@@ -294,4 +297,40 @@ public class StandaloneConfigTaskExecutor implements IConfigTaskExecutor {
"Executing show datanodes in standalone mode is not supported")));
return future;
}
+
+ @Override
+ public SettableFuture<ConfigTaskResult> createSchemaTemplate(
+ CreateSchemaTemplateStatement createSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ future.setException(
+ new StatementExecutionException(
+ RpcUtils.getStatus(
+ TSStatusCode.EXECUTE_STATEMENT_ERROR,
+ "Executing create schema template is not supported")));
+ return future;
+ }
+
+ @Override
+ public SettableFuture<ConfigTaskResult> showSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ future.setException(
+ new StatementExecutionException(
+ RpcUtils.getStatus(
+ TSStatusCode.EXECUTE_STATEMENT_ERROR,
+ "Executing show schema template is not supported")));
+ return future;
+ }
+
+ @Override
+ public SettableFuture<ConfigTaskResult> showNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement) {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ future.setException(
+ new StatementExecutionException(
+ RpcUtils.getStatus(
+ TSStatusCode.EXECUTE_STATEMENT_ERROR,
+ "Executing show nodes in schema template is not supported")));
+ return future;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index e5347b27e1..7aa614fac7 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -104,6 +104,9 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.UnSetTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.FlushStatement;
@@ -2311,4 +2314,159 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
public Statement visitShowDataNodes(IoTDBSqlParser.ShowDataNodesContext ctx) {
return new ShowDataNodesStatement();
}
+
+ @Override
+ public Statement visitCreateSchemaTemplate(IoTDBSqlParser.CreateSchemaTemplateContext ctx) {
+ CreateSchemaTemplateStatement createTemplateStatement = new CreateSchemaTemplateStatement();
+ String name = parseIdentifier(ctx.templateName.getText());
+ List<List<String>> measurementsList = new ArrayList<List<String>>();
+ List<List<TSDataType>> dataTypesList = new ArrayList<List<TSDataType>>();
+ List<List<TSEncoding>> encodingsList = new ArrayList<List<TSEncoding>>();
+ List<List<CompressionType>> compressorsList = new ArrayList<List<CompressionType>>();
+
+ if (ctx.ALIGNED() != null) {
+ // aligned
+ List<String> measurements = new ArrayList<>();
+ List<TSDataType> dataTypes = new ArrayList<>();
+ List<TSEncoding> encodings = new ArrayList<>();
+ List<CompressionType> compressors = new ArrayList<>();
+ for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
+ ctx.templateMeasurementClause()) {
+ measurements.add(
+ parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
+ parseAttributeClause(
+ templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
+ }
+ measurementsList.add(measurements);
+ dataTypesList.add(dataTypes);
+ encodingsList.add(encodings);
+ compressorsList.add(compressors);
+ } else {
+ // non-aligned
+ for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
+ ctx.templateMeasurementClause()) {
+ List<String> measurements = new ArrayList<>();
+ List<TSDataType> dataTypes = new ArrayList<>();
+ List<TSEncoding> encodings = new ArrayList<>();
+ List<CompressionType> compressors = new ArrayList<>();
+ measurements.add(
+ parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
+ parseAttributeClause(
+ templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
+ measurementsList.add(measurements);
+ dataTypesList.add(dataTypes);
+ encodingsList.add(encodings);
+ compressorsList.add(compressors);
+ }
+ }
+
+ createTemplateStatement =
+ new CreateSchemaTemplateStatement(
+ name, measurementsList, dataTypesList, encodingsList, compressorsList);
+ return createTemplateStatement;
+ }
+
+ void parseAttributeClause(
+ IoTDBSqlParser.AttributeClausesContext ctx,
+ List<TSDataType> dataTypes,
+ List<TSEncoding> encodings,
+ List<CompressionType> compressors) {
+ if (ctx.aliasNodeName() != null) {
+ throw new SQLParserException("schema template: alias is not supported yet.");
+ }
+
+ TSDataType dataType = null;
+ if (ctx.dataType != null) {
+ if (ctx.attributeKey() != null) {
+ if (!parseAttributeKey(ctx.attributeKey())
+ .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
+ throw new SQLParserException("expecting datatype");
+ }
+ }
+ String dataTypeString = ctx.dataType.getText().toUpperCase();
+ try {
+ dataType = TSDataType.valueOf(dataTypeString);
+ dataTypes.add(dataType);
+ } catch (Exception e) {
+ throw new SemanticException(String.format("unsupported datatype: %s", dataTypeString));
+ }
+ }
+
+ Map<String, String> props = new HashMap<>();
+ if (ctx.attributePair() != null) {
+ for (int i = 0; i < ctx.attributePair().size(); i++) {
+ props.put(
+ parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
+ parseAttributeValue(ctx.attributePair(i).attributeValue()));
+ }
+ }
+
+ TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
+ if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
+ String encodingString =
+ props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
+ try {
+ encoding = TSEncoding.valueOf(encodingString);
+ encodings.add(encoding);
+ props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
+ } catch (Exception e) {
+ throw new SemanticException(String.format("unsupported encoding: %s", encodingString));
+ }
+ } else {
+ encodings.add(encoding);
+ }
+
+ CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
+ if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
+ String compressorString =
+ props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
+ try {
+ compressor = CompressionType.valueOf(compressorString);
+ compressors.add(compressor);
+ props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
+ } catch (Exception e) {
+ throw new SemanticException(String.format("unsupported compressor: %s", compressorString));
+ }
+ } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
+ String compressionString =
+ props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
+ try {
+ compressor = CompressionType.valueOf(compressionString);
+ compressors.add(compressor);
+ props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
+ } catch (Exception e) {
+ throw new SemanticException(
+ String.format("unsupported compression: %s", compressionString));
+ }
+ } else {
+ compressors.add(compressor);
+ }
+
+ if (props.size() > 0) {
+ throw new SQLParserException("schema template: property is not supported yet.");
+ }
+
+ if (ctx.tagClause() != null) {
+ throw new SQLParserException("schema template: tag is not supported yet.");
+ }
+
+ if (ctx.attributeClause() != null) {
+ throw new SQLParserException("schema template: attribute is not supported yet.");
+ }
+ }
+
+ @Override
+ public Statement visitShowSchemaTemplates(IoTDBSqlParser.ShowSchemaTemplatesContext ctx) {
+ ShowSchemaTemplateStatement showSchemaTemplateStatement = new ShowSchemaTemplateStatement();
+ return showSchemaTemplateStatement;
+ }
+
+ @Override
+ public Statement visitShowNodesInSchemaTemplate(
+ IoTDBSqlParser.ShowNodesInSchemaTemplateContext ctx) {
+ String templateName = ctx.templateName.children.get(0).getText();
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement =
+ new ShowNodesInSchemaTemplateStatement(templateName);
+ return showNodesInSchemaTemplateStatement;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
index 2cff76f200..f9da937bff 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
@@ -56,15 +56,17 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.UnSetTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.FlushStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
/**
- * This class provides a visitor of {@link org.apache.iotdb.db.mpp.plan.statement.StatementNode},
- * which can be extended to create a visitor which only needs to handle a subset of the available
- * methods.
+ * This class provides a visitor of {@link StatementNode}, which can be extended to create a visitor
+ * which only needs to handle a subset of the available methods.
*
* @param <R> The return type of the visit operation.
* @param <C> The context information during visiting.
@@ -266,4 +268,19 @@ public abstract class StatementVisitor<R, C> {
public R visitShowVersion(ShowVersionStatement showVersionStatement, C context) {
return visitStatement(showVersionStatement, context);
}
+
+ public R visitCreateSchemaTemplate(
+ CreateSchemaTemplateStatement createTemplateStatement, C context) {
+ return visitStatement(createTemplateStatement, context);
+ }
+
+ public R visitShowNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement, C context) {
+ return visitStatement(showNodesInSchemaTemplateStatement, context);
+ }
+
+ public R visitShowSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement, C context) {
+ return visitStatement(showSchemaTemplateStatement, context);
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java
new file mode 100644
index 0000000000..299a96e2e4
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java
@@ -0,0 +1,181 @@
+/*
+ * 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.mpp.plan.statement.metadata.template;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.mpp.plan.analyze.QueryType;
+import org.apache.iotdb.db.mpp.plan.constant.StatementType;
+import org.apache.iotdb.db.mpp.plan.statement.IConfigStatement;
+import org.apache.iotdb.db.mpp.plan.statement.Statement;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class CreateSchemaTemplateStatement extends Statement implements IConfigStatement {
+
+ String name;
+ Set<String> alignedDeviceId;
+ String[][] measurements;
+ TSDataType[][] dataTypes;
+ TSEncoding[][] encodings;
+ CompressionType[][] compressors;
+
+ // constant to help resolve serialized sequence
+ private static final int NEW_PLAN = -1;
+
+ public CreateSchemaTemplateStatement() {
+ super();
+ statementType = StatementType.CREATE_TEMPLATE;
+ }
+
+ public CreateSchemaTemplateStatement(
+ String name,
+ List<List<String>> measurements,
+ List<List<TSDataType>> dataTypes,
+ List<List<TSEncoding>> encodings,
+ List<List<CompressionType>> compressors) {
+ this();
+ this.name = name;
+ this.measurements = new String[measurements.size()][];
+ for (int i = 0; i < measurements.size(); i++) {
+ this.measurements[i] = new String[measurements.get(i).size()];
+ for (int j = 0; j < measurements.get(i).size(); j++) {
+ this.measurements[i][j] = measurements.get(i).get(j);
+ }
+ }
+
+ this.dataTypes = new TSDataType[dataTypes.size()][];
+ for (int i = 0; i < dataTypes.size(); i++) {
+ this.dataTypes[i] = new TSDataType[dataTypes.get(i).size()];
+ for (int j = 0; j < dataTypes.get(i).size(); j++) {
+ this.dataTypes[i][j] = dataTypes.get(i).get(j);
+ }
+ }
+
+ this.encodings = new TSEncoding[dataTypes.size()][];
+ for (int i = 0; i < encodings.size(); i++) {
+ this.encodings[i] = new TSEncoding[dataTypes.get(i).size()];
+ for (int j = 0; j < encodings.get(i).size(); j++) {
+ this.encodings[i][j] = encodings.get(i).get(j);
+ }
+ }
+
+ this.compressors = new CompressionType[dataTypes.size()][];
+ for (int i = 0; i < compressors.size(); i++) {
+ this.compressors[i] = new CompressionType[compressors.get(i).size()];
+ for (int j = 0; j < compressors.get(i).size(); j++) {
+ this.compressors[i][j] = compressors.get(i).get(j);
+ }
+ }
+ this.alignedDeviceId = new HashSet<>();
+ }
+
+ private CreateSchemaTemplateStatement(
+ String name,
+ List<List<String>> measurements,
+ List<List<TSDataType>> dataTypes,
+ List<List<TSEncoding>> encodings,
+ List<List<CompressionType>> compressors,
+ Set<String> alignedDeviceId) {
+ // Only accessed by deserialization, which may cause ambiguity with align designation
+ this(name, measurements, dataTypes, encodings, compressors);
+ this.alignedDeviceId = alignedDeviceId;
+ }
+
+ public CreateSchemaTemplateStatement(
+ String name,
+ String[][] measurements,
+ TSDataType[][] dataTypes,
+ TSEncoding[][] encodings,
+ CompressionType[][] compressors) {
+ this();
+ this.name = name;
+ this.measurements = measurements;
+ this.dataTypes = dataTypes;
+ this.encodings = encodings;
+ this.compressors = compressors;
+ }
+
+ @Override
+ public List<? extends PartialPath> getPaths() {
+ return null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Set<String> getAlignedDeviceId() {
+ return alignedDeviceId;
+ }
+
+ public List<List<String>> getMeasurements() {
+ List<List<String>> ret = new ArrayList<>();
+ for (String[] measurement : measurements) {
+ ret.add(Arrays.asList(measurement));
+ }
+ return ret;
+ }
+
+ public List<List<TSDataType>> getDataTypes() {
+ List<List<TSDataType>> ret = new ArrayList<>();
+ for (TSDataType[] alignedDataTypes : dataTypes) {
+ ret.add(Arrays.asList(alignedDataTypes));
+ }
+ return ret;
+ }
+
+ public List<List<TSEncoding>> getEncodings() {
+ List<List<TSEncoding>> ret = new ArrayList<>();
+ for (TSEncoding[] alignedEncodings : encodings) {
+ ret.add(Arrays.asList(alignedEncodings));
+ }
+ return ret;
+ }
+
+ public List<List<CompressionType>> getCompressors() {
+ List<List<CompressionType>> ret = new ArrayList<>();
+ for (CompressionType[] alignedCompressor : compressors) {
+ ret.add(Arrays.asList(alignedCompressor));
+ }
+ return ret;
+ }
+
+ @Override
+ public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+ return visitor.visitCreateSchemaTemplate(this, context);
+ }
+
+ @Override
+ public QueryType getQueryType() {
+ return QueryType.WRITE;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowNodesInSchemaTemplateStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowNodesInSchemaTemplateStatement.java
new file mode 100644
index 0000000000..dacfc93d8f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowNodesInSchemaTemplateStatement.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.plan.statement.metadata.template;
+
+import org.apache.iotdb.db.mpp.plan.analyze.QueryType;
+import org.apache.iotdb.db.mpp.plan.constant.StatementType;
+import org.apache.iotdb.db.mpp.plan.statement.IConfigStatement;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStatement;
+
+public class ShowNodesInSchemaTemplateStatement extends ShowStatement implements IConfigStatement {
+
+ private String templateName;
+
+ public ShowNodesInSchemaTemplateStatement(String templateName) {
+ super();
+ statementType = StatementType.SHOW_NODES_IN_SCHEMA_TEMPLATE;
+ this.templateName = templateName;
+ }
+
+ @Override
+ public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+ return visitor.visitShowNodesInSchemaTemplate(this, context);
+ }
+
+ public String getTemplateName() {
+ return templateName;
+ }
+
+ public void setTemplateName(String templateName) {
+ this.templateName = templateName;
+ }
+
+ @Override
+ public QueryType getQueryType() {
+ return QueryType.READ;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowSchemaTemplateStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowSchemaTemplateStatement.java
new file mode 100644
index 0000000000..e2744d8d1b
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/ShowSchemaTemplateStatement.java
@@ -0,0 +1,44 @@
+/*
+ * 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.mpp.plan.statement.metadata.template;
+
+import org.apache.iotdb.db.mpp.plan.analyze.QueryType;
+import org.apache.iotdb.db.mpp.plan.constant.StatementType;
+import org.apache.iotdb.db.mpp.plan.statement.IConfigStatement;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStatement;
+
+public class ShowSchemaTemplateStatement extends ShowStatement implements IConfigStatement {
+
+ public ShowSchemaTemplateStatement() {
+ super();
+ statementType = StatementType.SHOW_SCHEMA_TEMPLATE;
+ }
+
+ @Override
+ public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+ return visitor.visitShowSchemaTemplate(this, context);
+ }
+
+ @Override
+ public QueryType getQueryType() {
+ return QueryType.READ;
+ }
+}
diff --git a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index 146068ccd7..cc7370a6fd 100644
--- a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -68,6 +68,8 @@ public enum TSStatusCode {
PIPESERVER_ERROR(336),
SERIES_OVERFLOW(337),
MEASUREMENT_ALREADY_EXIST(338),
+ TEMPLATE_NOT_EXIST(339),
+ CREATE_TEMPLATE_ERROR(340),
EXECUTE_STATEMENT_ERROR(400),
SQL_PARSE_ERROR(401),
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift b/thrift-confignode/src/main/thrift/confignode.thrift
index 973b383df7..4ee1753aaa 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -264,6 +264,23 @@ struct TRegionRouteMapResp {
3: optional map<common.TConsensusGroupId, common.TRegionReplicaSet> regionRouteMap
}
+
+// Template
+struct TCreateSchemaTemplateReq {
+ 1: required string name
+ 2: required binary serializedTemplate
+}
+
+struct TGetAllTemplatesResp {
+ 1: required common.TSStatus status
+ 2: optional list<binary> templateList
+}
+
+struct TGetTemplateResp {
+ 1: required common.TSStatus status
+ 2: optional binary template
+}
+
service IConfigNodeRPCService {
/* DataNode */
@@ -373,5 +390,13 @@ service IConfigNodeRPCService {
TShowDataNodesResp showDataNodes()
+ /* Template */
+
+ common.TSStatus createSchemaTemplate(TCreateSchemaTemplateReq req)
+
+ TGetAllTemplatesResp getAllTemplates()
+
+ TGetTemplateResp getTemplate(string req)
+
}