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
     ;

Reply via email to