This is an automated email from the ASF dual-hosted git repository.
Caideyipi pushed a commit to branch show-create-remain
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/show-create-remain by this
push:
new aca2e132e13 ut
aca2e132e13 is described below
commit aca2e132e1306a459b07be31ecbeb030c68c59c3
Author: Caideyipi <[email protected]>
AuthorDate: Mon May 18 12:09:17 2026 +0800
ut
---
.../relational/it/schema/IoTDBDatabaseIT.java | 45 ++++++
.../common/header/DatasetHeaderFactory.java | 8 +
.../execution/config/TableConfigTaskVisitor.java | 19 +++
.../config/executor/ClusterConfigTaskExecutor.java | 104 ++++++++++++
.../config/executor/IConfigTaskExecutor.java | 4 +
.../relational/ShowCreateDatabaseTask.java | 96 +++++++++++
.../metadata/relational/ShowCreatePipeTask.java | 176 +++++++++++++++++++++
.../relational/analyzer/StatementAnalyzer.java | 12 ++
.../plan/relational/sql/ast/AstVisitor.java | 8 +
.../relational/sql/ast/ShowCreateDatabase.java | 92 +++++++++++
.../plan/relational/sql/ast/ShowCreatePipe.java | 84 ++++++++++
.../plan/relational/sql/parser/AstBuilder.java | 14 ++
.../relational/sql/util/DataNodeSqlFormatter.java | 19 +++
.../metadata/relational/ShowCreateTaskTest.java | 146 +++++++++++++++++
.../schema/column/ColumnHeaderConstant.java | 12 ++
.../db/relational/grammar/sql/RelationalSql.g4 | 10 ++
16 files changed, 849 insertions(+)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
index 2b367b70b22..ebed28f0433 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
@@ -285,6 +285,51 @@ public class IoTDBDatabaseIT {
}
}
+ @Test
+ public void testShowCreateDatabase() throws SQLException {
+ try (final Connection connection =
+ EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ final Statement statement = connection.createStatement()) {
+ statement.execute(
+ "create database test_show_create_db with (ttl=300,
schema_region_group_num=DEFAULT, data_region_group_num=DEFAULT,
time_partition_interval=100000)");
+
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show create database test_show_create_db"),
+ "Database,Create Database,",
+ Collections.singleton(
+ "test_show_create_db,CREATE DATABASE \"test_show_create_db\"
WITH
(ttl=300,time_partition_interval=100000,schema_region_group_num=0,data_region_group_num=0),"));
+ }
+ }
+
+ @Test
+ public void testShowCreatePipe() throws SQLException {
+ try (final Connection connection =
+ EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ final Statement statement = connection.createStatement()) {
+ statement.execute("create pipe test_show_create_pipe
('sink'='do-nothing-sink')");
+
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show create pipe test_show_create_pipe"),
+ "Pipe,Create Pipe,",
+ Collections.singleton(
+ "test_show_create_pipe,CREATE PIPE \"test_show_create_pipe\"
WITH SINK ('sink'='do-nothing-sink'),"));
+ }
+ }
+
+ @Test
+ public void testShowCreateInformationSchemaDatabase() throws SQLException {
+ try (final Connection connection =
+ EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ final Statement statement = connection.createStatement()) {
+ try {
+ statement.executeQuery("show create database information_schema");
+ fail("show create database information_schema shouldn't succeed");
+ } catch (final SQLException e) {
+ assertEquals("701: The system database does not support show create.",
e.getMessage());
+ }
+ }
+ }
+
@Test
public void testDatabaseWithSpecificCharacters() throws SQLException {
try (final Connection connection =
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
index 18f15eea8f3..b2c327b866a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
@@ -263,6 +263,14 @@ public class DatasetHeaderFactory {
return new
DatasetHeader(ColumnHeaderConstant.showCreateTableColumnHeaders, true);
}
+ public static DatasetHeader getShowCreatePipeColumnHeader() {
+ return new DatasetHeader(ColumnHeaderConstant.showCreatePipeColumnHeaders,
true);
+ }
+
+ public static DatasetHeader getShowCreateDatabaseColumnHeader() {
+ return new
DatasetHeader(ColumnHeaderConstant.showCreateDatabaseColumnHeaders, true);
+ }
+
public static DatasetHeader getShowTablesHeader() {
return new DatasetHeader(ColumnHeaderConstant.showTablesColumnHeaders,
true);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index e07bc920313..4400b039d9a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -110,6 +110,8 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.RelationalAuthorizerTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowAINodesTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowConfigNodesTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateDatabaseTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreatePipeTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateTableTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateViewTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowDBTask;
@@ -209,6 +211,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCluster;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowClusterId;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowConfigNodes;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowConfiguration;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateDatabase;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreatePipe;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentDatabase;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentSqlDialect;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentTimestamp;
@@ -424,6 +428,15 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
canShowDB(accessControl, context.getSession().getUserName(),
databaseName, context));
}
+ @Override
+ public IConfigTask visitShowCreateDatabase(
+ final ShowCreateDatabase node, final MPPQueryContext context) {
+ context.setQueryType(QueryType.READ);
+ accessControl.checkCanShowOrUseDatabase(
+ context.getSession().getUserName(), node.getDatabase(), context);
+ return new ShowCreateDatabaseTask(node.getDatabase());
+ }
+
public static boolean canShowDB(
final AccessControl accessControl,
final String userName,
@@ -1341,6 +1354,12 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
return new ShowPipeTask(node, context.getSession().getUserName());
}
+ @Override
+ public IConfigTask visitShowCreatePipe(ShowCreatePipe node, MPPQueryContext
context) {
+ context.setQueryType(QueryType.READ);
+ return new ShowCreatePipeTask(node.getPipeName(),
context.getSession().getUserName());
+ }
+
@Override
public IConfigTask visitCreatePipePlugin(CreatePipePlugin node,
MPPQueryContext context) {
context.setQueryType(QueryType.OTHER);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 3f632c9a987..274eb568233 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -81,6 +81,7 @@ import
org.apache.iotdb.commons.schema.cache.CacheClearOptions;
import org.apache.iotdb.commons.schema.column.ColumnHeader;
import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
import org.apache.iotdb.commons.schema.table.AlterOrDropTableOperationType;
+import org.apache.iotdb.commons.schema.table.InformationSchema;
import org.apache.iotdb.commons.schema.table.TsTable;
import org.apache.iotdb.commons.schema.table.TsTableInternalRPCUtil;
import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
@@ -118,6 +119,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TCreateTopicReq;
import org.apache.iotdb.confignode.rpc.thrift.TCreateTriggerReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveReq;
import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveResp;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo;
import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
import org.apache.iotdb.confignode.rpc.thrift.TDeactivateSchemaTemplateReq;
import org.apache.iotdb.confignode.rpc.thrift.TDeleteDatabasesReq;
@@ -162,6 +164,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TShowDatabaseResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeInfo;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipePluginReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
+import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
@@ -232,6 +235,8 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.Rem
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DeleteDeviceTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DescribeTableDetailsTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DescribeTableTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateDatabaseTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreatePipeTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateTableTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateViewTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowDBTask;
@@ -2740,6 +2745,65 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
return future;
}
+ @Override
+ public SettableFuture<ConfigTaskResult> showCreatePipe(
+ final String pipeName, final String userName) {
+ final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ try (final ConfigNodeClient configNodeClient =
+
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+ final TShowPipeReq tShowPipeReq =
+ new TShowPipeReq().setPipeName(pipeName).setIsTableModel(true);
+ if (Objects.nonNull(userName)) {
+ tShowPipeReq.setUserName(userName);
+ }
+ final TShowPipeResp showPipeResp =
configNodeClient.showPipe(tShowPipeReq);
+ if (showPipeResp.getStatus().getCode() !=
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ future.setException(new IoTDBException(showPipeResp.getStatus()));
+ return future;
+ }
+ if (!showPipeResp.isSetPipeInfoList() ||
showPipeResp.getPipeInfoList().isEmpty()) {
+ future.setException(
+ new IoTDBException(
+ String.format("Failed to show create pipe %s, the pipe does
not exist.", pipeName),
+ TSStatusCode.PIPE_NOT_EXIST_ERROR.getStatusCode()));
+ return future;
+ }
+
+ final TGetAllPipeInfoResp getAllPipeInfoResp =
configNodeClient.getAllPipeInfo();
+ if (getAllPipeInfoResp.getStatus().getCode() !=
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ future.setException(
+ new IoTDBException(
+ String.format(
+ "Failed to get pipe info from config node, status is %s.",
+ getAllPipeInfoResp.getStatus()),
+ TSStatusCode.PIPE_ERROR.getStatusCode()));
+ return future;
+ }
+
+ final PipeMeta pipeMeta =
+ getAllPipeInfoResp.getAllPipeInfo().stream()
+ .map(PipeMeta::deserialize4Coordinator)
+ .filter(
+ meta ->
+ meta.getStaticMeta().visibleUnder(true)
+ &&
meta.getStaticMeta().getPipeName().equals(pipeName))
+ .findFirst()
+ .orElse(null);
+ if (pipeMeta == null) {
+ future.setException(
+ new IoTDBException(
+ String.format("Failed to show create pipe %s, the pipe does
not exist.", pipeName),
+ TSStatusCode.PIPE_NOT_EXIST_ERROR.getStatusCode()));
+ return future;
+ }
+
+ ShowCreatePipeTask.buildTsBlock(pipeMeta, future);
+ } catch (final Exception e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
@Override
public SettableFuture<ConfigTaskResult> showSubscriptions(
final ShowSubscriptionsStatement showSubscriptionsStatement) {
@@ -4140,6 +4204,46 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
return future;
}
+ @Override
+ public SettableFuture<ConfigTaskResult> showCreateDatabase(final String
database) {
+ final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ if (InformationSchema.INFORMATION_DATABASE.equals(database)) {
+ future.setException(
+ new IoTDBException(
+ "The system database does not support show create.",
+ TSStatusCode.SEMANTIC_ERROR.getStatusCode()));
+ return future;
+ }
+
+ final List<String> databasePathPattern = Arrays.asList(ROOT, database);
+ try (final ConfigNodeClient client =
+
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+ final TGetDatabaseReq req =
+ new TGetDatabaseReq(databasePathPattern, ALL_MATCH_SCOPE.serialize())
+ .setIsTableModel(true);
+ final TShowDatabaseResp resp = client.showDatabase(req);
+ if (resp.getStatus().getCode() !=
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ future.setException(new IoTDBException(resp.getStatus()));
+ return future;
+ }
+
+ final TDatabaseInfo databaseInfo =
+ resp.isSetDatabaseInfoMap() ?
resp.getDatabaseInfoMap().get(database) : null;
+ if (databaseInfo == null) {
+ future.setException(
+ new IoTDBException(
+ String.format("Unknown database %s", database),
+ TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()));
+ return future;
+ }
+
+ ShowCreateDatabaseTask.buildTsBlock(databaseInfo, future);
+ } catch (final IOException | ClientManagerException | TException e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
@Override
public SettableFuture<ConfigTaskResult> showCluster(final ShowCluster
showCluster) {
// As the implementation is identical, we'll simply translate to the
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
index b4b928ba0b6..3a2c55d6861 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -234,6 +234,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showPipes(
ShowPipesStatement showPipesStatement, String userName);
+ SettableFuture<ConfigTaskResult> showCreatePipe(String pipeName, String
userName);
+
SettableFuture<ConfigTaskResult> showSubscriptions(
ShowSubscriptionsStatement showSubscriptionsStatement);
@@ -333,6 +335,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showDatabases(
final ShowDB showDB, final Predicate<String> canSeenDB);
+ SettableFuture<ConfigTaskResult> showCreateDatabase(final String database);
+
SettableFuture<ConfigTaskResult> showCluster(ShowCluster showCluster);
SettableFuture<ConfigTaskResult> useDatabase(final Use useDB, final
IClientSession clientSession);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateDatabaseTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateDatabaseTask.java
new file mode 100644
index 00000000000..9fe527a01dd
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateDatabaseTask.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.schema.column.ColumnHeader;
+import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeaderFactory;
+import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
+import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.tsfile.utils.Binary;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ShowCreateDatabaseTask implements IConfigTask {
+
+ private final String database;
+
+ public ShowCreateDatabaseTask(final String database) {
+ this.database = database;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(final IConfigTaskExecutor
configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showCreateDatabase(database);
+ }
+
+ public static void buildTsBlock(
+ final TDatabaseInfo databaseInfo, final SettableFuture<ConfigTaskResult>
future) {
+ final List<TSDataType> outputDataTypes =
+ ColumnHeaderConstant.showCreateDatabaseColumnHeaders.stream()
+ .map(ColumnHeader::getColumnType)
+ .collect(Collectors.toList());
+
+ final TsBlockBuilder builder = new TsBlockBuilder(outputDataTypes);
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder
+ .getColumnBuilder(0)
+ .writeBinary(new Binary(databaseInfo.getName(),
TSFileConfig.STRING_CHARSET));
+ builder
+ .getColumnBuilder(1)
+ .writeBinary(
+ new Binary(getShowCreateDatabaseSQL(databaseInfo),
TSFileConfig.STRING_CHARSET));
+ builder.declarePosition();
+
+ final DatasetHeader datasetHeader =
DatasetHeaderFactory.getShowCreateDatabaseColumnHeader();
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS,
builder.build(), datasetHeader));
+ }
+
+ public static String getShowCreateDatabaseSQL(final TDatabaseInfo
databaseInfo) {
+ return new StringBuilder("CREATE DATABASE ")
+ .append(ShowCreateTableTask.getIdentifier(databaseInfo.getName()))
+ .append(" WITH (ttl=")
+ .append(
+ databaseInfo.getTTL() == Long.MAX_VALUE
+ ? ShowCreateTableTask.getString(IoTDBConstant.TTL_INFINITE)
+ : databaseInfo.getTTL())
+ .append(",time_partition_interval=")
+ .append(databaseInfo.getTimePartitionInterval())
+ .append(",schema_region_group_num=")
+ .append(databaseInfo.getMinSchemaRegionNum())
+ .append(",data_region_group_num=")
+ .append(databaseInfo.getMinDataRegionNum())
+ .append(")")
+ .toString();
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreatePipeTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreatePipeTask.java
new file mode 100644
index 00000000000..7f7185e0a79
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreatePipeTask.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational;
+
+import org.apache.iotdb.commons.pipe.agent.task.meta.PipeMeta;
+import org.apache.iotdb.commons.pipe.config.constant.PipeSinkConstant;
+import org.apache.iotdb.commons.pipe.config.constant.PipeSourceConstant;
+import org.apache.iotdb.commons.pipe.config.constant.SystemConstant;
+import org.apache.iotdb.commons.schema.column.ColumnHeader;
+import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeaderFactory;
+import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
+import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.tsfile.utils.Binary;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+public class ShowCreatePipeTask implements IConfigTask {
+
+ private final String pipeName;
+ private final String userName;
+
+ public ShowCreatePipeTask(final String pipeName, final String userName) {
+ this.pipeName = pipeName;
+ this.userName = userName;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(final IConfigTaskExecutor
configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showCreatePipe(pipeName, userName);
+ }
+
+ public static void buildTsBlock(
+ final PipeMeta pipeMeta, final SettableFuture<ConfigTaskResult> future) {
+ final List<TSDataType> outputDataTypes =
+ ColumnHeaderConstant.showCreatePipeColumnHeaders.stream()
+ .map(ColumnHeader::getColumnType)
+ .collect(Collectors.toList());
+
+ final TsBlockBuilder builder = new TsBlockBuilder(outputDataTypes);
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder
+ .getColumnBuilder(0)
+ .writeBinary(
+ new Binary(pipeMeta.getStaticMeta().getPipeName(),
TSFileConfig.STRING_CHARSET));
+ builder
+ .getColumnBuilder(1)
+ .writeBinary(new Binary(getShowCreatePipeSQL(pipeMeta),
TSFileConfig.STRING_CHARSET));
+ builder.declarePosition();
+
+ final DatasetHeader datasetHeader =
DatasetHeaderFactory.getShowCreatePipeColumnHeader();
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS,
builder.build(), datasetHeader));
+ }
+
+ public static String getShowCreatePipeSQL(final PipeMeta pipeMeta) {
+ final StringBuilder builder =
+ new StringBuilder("CREATE PIPE ")
+
.append(ShowCreateTableTask.getIdentifier(pipeMeta.getStaticMeta().getPipeName()));
+
+ appendAttributesClause(
+ builder,
+ "WITH SOURCE",
+
sanitizeSourceAttributes(pipeMeta.getStaticMeta().getSourceParameters().getAttribute()));
+ appendAttributesClause(
+ builder,
+ "WITH PROCESSOR",
+
sanitizeCommonAttributes(pipeMeta.getStaticMeta().getProcessorParameters().getAttribute()));
+ appendAttributesClause(
+ builder,
+ "WITH SINK",
+
sanitizeSinkAttributes(pipeMeta.getStaticMeta().getSinkParameters().getAttribute()));
+
+ return builder.toString();
+ }
+
+ private static Map<String, String> sanitizeCommonAttributes(
+ final Map<String, String> attributes) {
+ final Map<String, String> result = new TreeMap<>(attributes);
+ result
+ .entrySet()
+ .removeIf(entry ->
entry.getKey().startsWith(SystemConstant.SYSTEM_PREFIX_KEY));
+ result.entrySet().removeIf(entry ->
entry.getKey().startsWith(SystemConstant.AUDIT_PREFIX_KEY));
+ return result;
+ }
+
+ private static Map<String, String> sanitizeSourceAttributes(final
Map<String, String> source) {
+ final Map<String, String> result = sanitizeCommonAttributes(source);
+ result.remove(PipeSourceConstant.EXTRACTOR_IOTDB_USER_ID);
+ result.remove(PipeSourceConstant.SOURCE_IOTDB_USER_ID);
+ result.remove(PipeSourceConstant.EXTRACTOR_IOTDB_CLI_HOSTNAME);
+ result.remove(PipeSourceConstant.SOURCE_IOTDB_CLI_HOSTNAME);
+ if (!hasAnyKey(
+ result,
+ PipeSourceConstant.EXTRACTOR_IOTDB_PASSWORD_KEY,
+ PipeSourceConstant.SOURCE_IOTDB_PASSWORD_KEY)) {
+ result.remove(PipeSourceConstant.EXTRACTOR_IOTDB_USER_KEY);
+ result.remove(PipeSourceConstant.SOURCE_IOTDB_USER_KEY);
+ result.remove(PipeSourceConstant.EXTRACTOR_IOTDB_USERNAME_KEY);
+ result.remove(PipeSourceConstant.SOURCE_IOTDB_USERNAME_KEY);
+ }
+ return result;
+ }
+
+ private static Map<String, String> sanitizeSinkAttributes(final Map<String,
String> sink) {
+ final Map<String, String> result = sanitizeCommonAttributes(sink);
+ result.remove(PipeSinkConstant.CONNECTOR_IOTDB_USER_ID);
+ result.remove(PipeSinkConstant.SINK_IOTDB_USER_ID);
+ result.remove(PipeSinkConstant.CONNECTOR_IOTDB_CLI_HOSTNAME);
+ result.remove(PipeSinkConstant.SINK_IOTDB_CLI_HOSTNAME);
+ if (!hasAnyKey(
+ result,
+ PipeSinkConstant.CONNECTOR_IOTDB_PASSWORD_KEY,
+ PipeSinkConstant.SINK_IOTDB_PASSWORD_KEY)) {
+ result.remove(PipeSinkConstant.CONNECTOR_IOTDB_USER_KEY);
+ result.remove(PipeSinkConstant.SINK_IOTDB_USER_KEY);
+ result.remove(PipeSinkConstant.CONNECTOR_IOTDB_USERNAME_KEY);
+ result.remove(PipeSinkConstant.SINK_IOTDB_USERNAME_KEY);
+ }
+ return result;
+ }
+
+ private static void appendAttributesClause(
+ final StringBuilder builder, final String clause, final Map<String,
String> attributes) {
+ if (attributes.isEmpty()) {
+ return;
+ }
+ final List<String> pairs = new ArrayList<>(attributes.size());
+ for (final Map.Entry<String, String> entry : attributes.entrySet()) {
+ pairs.add(
+ ShowCreateTableTask.getString(entry.getKey())
+ + "="
+ + ShowCreateTableTask.getString(entry.getValue()));
+ }
+ builder.append(" ").append(clause).append(" (").append(String.join(",",
pairs)).append(")");
+ }
+
+ private static boolean hasAnyKey(final Map<String, String> attributes, final
String... keys) {
+ for (final String key : keys) {
+ if (attributes.containsKey(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index d0779ee24a5..17cd05b8bbb 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -184,6 +184,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Property;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameColumn;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RenameTable;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetProperties;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateDatabase;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreatePipe;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowFunctions;
@@ -448,6 +450,11 @@ public class StatementAnalyzer {
DataNodeQueryMessages.SHOW_DATABASE_STATEMENT_IS_NOT_SUPPORTED_YET);
}
+ @Override
+ public Scope visitShowCreateDatabase(ShowCreateDatabase node,
Optional<Scope> context) {
+ return createAndAssignScope(node, context);
+ }
+
@Override
public Scope visitCreateTable(final CreateTable node, final
Optional<Scope> context) {
validateProperties(node.getProperties(), context);
@@ -4817,6 +4824,11 @@ public class StatementAnalyzer {
return createAndAssignScope(node, context);
}
+ @Override
+ public Scope visitShowCreatePipe(ShowCreatePipe node, Optional<Scope>
context) {
+ return createAndAssignScope(node, context);
+ }
+
@Override
public Scope visitCreatePipePlugin(CreatePipePlugin node, Optional<Scope>
context) {
return createAndAssignScope(node, context);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
index 2e236e116e8..721323ee2d8 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
@@ -79,6 +79,10 @@ public interface AstVisitor<R, C> extends
CommonQueryAstVisitor<R, C> {
return visitStatement(node, context);
}
+ default R visitShowCreateDatabase(final ShowCreateDatabase node, final C
context) {
+ return visitStatement(node, context);
+ }
+
default R visitCreateTable(final CreateTable node, final C context) {
return visitStatement(node, context);
}
@@ -315,6 +319,10 @@ public interface AstVisitor<R, C> extends
CommonQueryAstVisitor<R, C> {
return visitStatement(node, context);
}
+ default R visitShowCreatePipe(ShowCreatePipe node, C context) {
+ return visitStatement(node, context);
+ }
+
default R visitCreatePipePlugin(CreatePipePlugin node, C context) {
return visitStatement(node, context);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreateDatabase.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreateDatabase.java
new file mode 100644
index 00000000000..330a7145faa
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreateDatabase.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
+
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.AstMemoryEstimationHelper;
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.IAstVisitor;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Node;
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.NodeLocation;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tsfile.utils.RamUsageEstimator;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class ShowCreateDatabase extends Statement {
+
+ private static final long INSTANCE_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(ShowCreateDatabase.class);
+
+ private final String database;
+
+ public ShowCreateDatabase(final NodeLocation location, final String
database) {
+ super(requireNonNull(location, "location is null"));
+ this.database = requireNonNull(database, "database is
null").toLowerCase(Locale.ENGLISH);
+ }
+
+ public String getDatabase() {
+ return database;
+ }
+
+ @Override
+ public <R, C> R accept(final IAstVisitor<R, C> visitor, final C context) {
+ return ((AstVisitor<R, C>) visitor).visitShowCreateDatabase(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(database);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final ShowCreateDatabase that = (ShowCreateDatabase) obj;
+ return Objects.equals(database, that.database);
+ }
+
+ @Override
+ public String toString() {
+ return "SHOW CREATE DATABASE " + database;
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long size = INSTANCE_SIZE;
+ size +=
AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
+ size += RamUsageEstimator.sizeOf(database);
+ return size;
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreatePipe.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreatePipe.java
new file mode 100644
index 00000000000..a9a6c4cbe59
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreatePipe.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
+
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.AstMemoryEstimationHelper;
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.IAstVisitor;
+
+import org.apache.tsfile.utils.RamUsageEstimator;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class ShowCreatePipe extends PipeStatement {
+
+ private static final long INSTANCE_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(ShowCreatePipe.class);
+
+ private final String pipeName;
+
+ public ShowCreatePipe(final String pipeName) {
+ this.pipeName = requireNonNull(pipeName, "pipeName is null");
+ }
+
+ public String getPipeName() {
+ return pipeName;
+ }
+
+ @Override
+ public <R, C> R accept(final IAstVisitor<R, C> visitor, final C context) {
+ return ((AstVisitor<R, C>) visitor).visitShowCreatePipe(this, context);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(pipeName);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final ShowCreatePipe that = (ShowCreatePipe) obj;
+ return Objects.equals(pipeName, that.pipeName);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("statement", "SHOW CREATE PIPE")
+ .add("pipeName", pipeName)
+ .toString();
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long size = INSTANCE_SIZE;
+ size +=
AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
+ size += RamUsageEstimator.sizeOf(pipeName);
+ return size;
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 768a05689e8..f83f54ac65d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -224,6 +224,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCluster;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowClusterId;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowConfigNodes;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowConfiguration;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateDatabase;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreatePipe;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentDatabase;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentSqlDialect;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentTimestamp;
@@ -406,6 +408,13 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
return new ShowDB(getLocation(ctx), Objects.nonNull(ctx.DETAILS()));
}
+ @Override
+ public Node visitShowCreateDatabaseStatement(
+ final RelationalSqlParser.ShowCreateDatabaseStatementContext ctx) {
+ return new ShowCreateDatabase(
+ getLocation(ctx), lowerIdentifier((Identifier)
visit(ctx.database)).getValue());
+ }
+
@Override
public Node visitCreateDbStatement(final
RelationalSqlParser.CreateDbStatementContext ctx) {
List<Property> properties = ImmutableList.of();
@@ -1332,6 +1341,11 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
return new ShowPipes(pipeName, hasWhereClause);
}
+ @Override
+ public Node
visitShowCreatePipeStatement(RelationalSqlParser.ShowCreatePipeStatementContext
ctx) {
+ return new ShowCreatePipe(((Identifier) visit(ctx.pipeName)).getValue());
+ }
+
@Override
public Node visitCreatePipePluginStatement(
RelationalSqlParser.CreatePipePluginStatementContext ctx) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
index 4797d43cf21..b036ea29915 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
@@ -26,6 +26,7 @@ import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Relation;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Table;
import
org.apache.iotdb.commons.queryengine.plan.relational.sql.util.CommonQuerySqlFormatter;
import org.apache.iotdb.db.i18n.DataNodeQueryMessages;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateTableTask;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AddColumn;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterPipe;
@@ -60,6 +61,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetColumnComment;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetProperties;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetTableComment;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowClusterId;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateDatabase;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreatePipe;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentDatabase;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentSqlDialect;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentTimestamp;
@@ -138,6 +141,14 @@ public final class DataNodeSqlFormatter extends
CommonQuerySqlFormatter
return null;
}
+ @Override
+ public Void visitShowCreateDatabase(ShowCreateDatabase node, Integer indent)
{
+ builder
+ .append("SHOW CREATE DATABASE ")
+ .append(ShowCreateTableTask.getIdentifier(node.getDatabase()));
+ return null;
+ }
+
@Override
public Void visitShowTables(ShowTables node, Integer indent) {
builder.append("SHOW TABLES");
@@ -697,6 +708,14 @@ public final class DataNodeSqlFormatter extends
CommonQuerySqlFormatter
return null;
}
+ @Override
+ public Void visitShowCreatePipe(ShowCreatePipe node, Integer context) {
+ builder
+ .append("SHOW CREATE PIPE ")
+ .append(ShowCreateTableTask.getIdentifier(node.getPipeName()));
+ return null;
+ }
+
@Override
public Void visitCreatePipePlugin(CreatePipePlugin node, Integer context) {
builder.append("CREATE PIPEPLUGIN ");
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateTaskTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateTaskTest.java
new file mode 100644
index 00000000000..dfa60953c9d
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateTaskTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.pipe.agent.task.meta.PipeMeta;
+import org.apache.iotdb.commons.pipe.agent.task.meta.PipeRuntimeMeta;
+import org.apache.iotdb.commons.pipe.agent.task.meta.PipeStaticMeta;
+import org.apache.iotdb.commons.pipe.config.constant.PipeProcessorConstant;
+import org.apache.iotdb.commons.pipe.config.constant.PipeSinkConstant;
+import org.apache.iotdb.commons.pipe.config.constant.PipeSourceConstant;
+import org.apache.iotdb.commons.pipe.config.constant.SystemConstant;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class ShowCreateTaskTest {
+
+ @Test
+ public void testShowCreateDatabaseSQL() {
+ final TDatabaseInfo databaseInfo = new TDatabaseInfo();
+ databaseInfo.setName("test_db");
+ databaseInfo.setTTL(Long.MAX_VALUE);
+ databaseInfo.setTimePartitionInterval(604800000L);
+ databaseInfo.setMinSchemaRegionNum(0);
+ databaseInfo.setMinDataRegionNum(1);
+
+ assertEquals(
+ "CREATE DATABASE \"test_db\" WITH (ttl='"
+ + IoTDBConstant.TTL_INFINITE
+ +
"',time_partition_interval=604800000,schema_region_group_num=0,data_region_group_num=1)",
+ ShowCreateDatabaseTask.getShowCreateDatabaseSQL(databaseInfo));
+ }
+
+ @Test
+ public void
testShowCreatePipeSQLShouldSanitizeInternalAndInjectedAttributes() {
+ final Map<String, String> sourceAttributes = new HashMap<>();
+ sourceAttributes.put(PipeSourceConstant.SOURCE_KEY, "iotdb-source");
+ sourceAttributes.put(SystemConstant.SQL_DIALECT_KEY,
SystemConstant.SQL_DIALECT_TABLE_VALUE);
+ sourceAttributes.put("__audit.source", "audit");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_USER_ID, "1");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_USERNAME_KEY,
"alice");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_CLI_HOSTNAME, "host");
+
+ final Map<String, String> processorAttributes = new HashMap<>();
+ processorAttributes.put(PipeProcessorConstant.PROCESSOR_KEY,
"do-nothing-processor");
+ processorAttributes.put(SystemConstant.RESTART_OR_NEWLY_ADDED_KEY, "true");
+ processorAttributes.put("__audit.processor", "audit");
+
+ final Map<String, String> sinkAttributes = new HashMap<>();
+ sinkAttributes.put(PipeSinkConstant.SINK_KEY, "write-back-sink");
+ sinkAttributes.put(SystemConstant.RESTART_OR_NEWLY_ADDED_KEY, "true");
+ sinkAttributes.put("__audit.sink", "audit");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_USER_ID, "1");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_USERNAME_KEY, "alice");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_CLI_HOSTNAME, "host");
+
+ final PipeMeta pipeMeta =
+ new PipeMeta(
+ new PipeStaticMeta(
+ "test_pipe", 1L, sourceAttributes, processorAttributes,
sinkAttributes),
+ new PipeRuntimeMeta());
+
+ assertEquals(
+ "CREATE PIPE \"test_pipe\" WITH SOURCE ('source'='iotdb-source')"
+ + " WITH PROCESSOR ('processor'='do-nothing-processor')"
+ + " WITH SINK ('sink'='write-back-sink')",
+ ShowCreatePipeTask.getShowCreatePipeSQL(pipeMeta));
+ }
+
+ @Test
+ public void testShowCreatePipeSQLShouldKeepExplicitCredentials() {
+ final Map<String, String> sourceAttributes = new HashMap<>();
+ sourceAttributes.put(PipeSourceConstant.SOURCE_KEY, "iotdb-source");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_USERNAME_KEY,
"alice");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_PASSWORD_KEY,
"secret");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_USER_ID, "1");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_CLI_HOSTNAME, "host");
+
+ final Map<String, String> sinkAttributes = new HashMap<>();
+ sinkAttributes.put(PipeSinkConstant.SINK_KEY, "write-back-sink");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_USERNAME_KEY, "alice");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_PASSWORD_KEY, "secret");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_USER_ID, "1");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_CLI_HOSTNAME, "host");
+
+ final PipeMeta pipeMeta =
+ new PipeMeta(
+ new PipeStaticMeta("test_pipe", 1L, sourceAttributes, new
HashMap<>(), sinkAttributes),
+ new PipeRuntimeMeta());
+
+ assertEquals(
+ "CREATE PIPE \"test_pipe\""
+ + " WITH SOURCE
('source'='iotdb-source','source.password'='secret','source.username'='alice')"
+ + " WITH SINK
('sink'='write-back-sink','sink.password'='secret','sink.username'='alice')",
+ ShowCreatePipeTask.getShowCreatePipeSQL(pipeMeta));
+ }
+
+ @Test
+ public void
testShowCreatePipeSQLShouldSanitizeExtractorAndConnectorAliases() {
+ final Map<String, String> sourceAttributes = new HashMap<>();
+ sourceAttributes.put(PipeSourceConstant.EXTRACTOR_KEY, "iotdb-extractor");
+ sourceAttributes.put(PipeSourceConstant.EXTRACTOR_IOTDB_USER_ID, "1");
+ sourceAttributes.put(PipeSourceConstant.EXTRACTOR_IOTDB_USERNAME_KEY,
"alice");
+ sourceAttributes.put(PipeSourceConstant.EXTRACTOR_IOTDB_CLI_HOSTNAME,
"host");
+
+ final Map<String, String> sinkAttributes = new HashMap<>();
+ sinkAttributes.put(PipeSinkConstant.CONNECTOR_KEY,
"iotdb-thrift-connector");
+ sinkAttributes.put(PipeSinkConstant.CONNECTOR_IOTDB_USER_ID, "1");
+ sinkAttributes.put(PipeSinkConstant.CONNECTOR_IOTDB_USERNAME_KEY, "alice");
+ sinkAttributes.put(PipeSinkConstant.CONNECTOR_IOTDB_CLI_HOSTNAME, "host");
+
+ final PipeMeta pipeMeta =
+ new PipeMeta(
+ new PipeStaticMeta("test_pipe", 1L, sourceAttributes, new
HashMap<>(), sinkAttributes),
+ new PipeRuntimeMeta());
+
+ assertEquals(
+ "CREATE PIPE \"test_pipe\""
+ + " WITH SOURCE ('extractor'='iotdb-extractor')"
+ + " WITH SINK ('connector'='iotdb-thrift-connector')",
+ ShowCreatePipeTask.getShowCreatePipeSQL(pipeMeta));
+ }
+}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
index 186f7daa684..0cd04f2585f 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
@@ -340,6 +340,9 @@ public class ColumnHeaderConstant {
public static final String CREATE_VIEW = "Create View";
public static final String TABLE = "Table";
public static final String CREATE_TABLE = "Create Table";
+ public static final String PIPE = "Pipe";
+ public static final String CREATE_PIPE = "Create Pipe";
+ public static final String CREATE_DATABASE = "Create Database";
public static final String GRANT_OPTION = "GrantOption";
@@ -755,6 +758,15 @@ public class ColumnHeaderConstant {
new ColumnHeader(TABLE, TSDataType.TEXT),
new ColumnHeader(CREATE_TABLE, TSDataType.TEXT));
+ public static final List<ColumnHeader> showCreatePipeColumnHeaders =
+ ImmutableList.of(
+ new ColumnHeader(PIPE, TSDataType.TEXT), new
ColumnHeader(CREATE_PIPE, TSDataType.TEXT));
+
+ public static final List<ColumnHeader> showCreateDatabaseColumnHeaders =
+ ImmutableList.of(
+ new ColumnHeader(DATABASE, TSDataType.TEXT),
+ new ColumnHeader(CREATE_DATABASE, TSDataType.TEXT));
+
public static final List<ColumnHeader> LIST_USER_COLUMN_HEADERS =
ImmutableList.of(
new ColumnHeader(USER_ID, TSDataType.INT64), new ColumnHeader(USER,
TSDataType.TEXT));
diff --git
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index ca766464686..9223bb6ae33 100644
---
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -49,6 +49,7 @@ statement
// Database Statement
| useDatabaseStatement
| showDatabasesStatement
+ | showCreateDatabaseStatement
| createDbStatement
| alterDbStatement
| dropDbStatement
@@ -101,6 +102,7 @@ statement
| startPipeStatement
| stopPipeStatement
| showPipesStatement
+ | showCreatePipeStatement
| createPipePluginStatement
| dropPipePluginStatement
| showPipePluginsStatement
@@ -203,6 +205,10 @@ showDatabasesStatement
: SHOW DATABASES (DETAILS)?
;
+showCreateDatabaseStatement
+ : SHOW CREATE DATABASE database=identifier
+ ;
+
createDbStatement
: CREATE DATABASE (IF NOT EXISTS)? database=identifier (WITH properties)?
;
@@ -514,6 +520,10 @@ showPipesStatement
: SHOW ((PIPE pipeName=identifier) | PIPES (WHERE (CONNECTOR | SINK) USED
BY pipeName=identifier)?)
;
+showCreatePipeStatement
+ : SHOW CREATE PIPE pipeName=identifier
+ ;
+
createPipePluginStatement
: CREATE PIPEPLUGIN (IF NOT EXISTS)? pluginName=identifier AS
className=string uriClause
;