This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new e948e49afbe Added show create pipe/database/topic (#17702)
e948e49afbe is described below
commit e948e49afbe8101ef5d9f13485096ec92e7caeb9
Author: Caideyipi <[email protected]>
AuthorDate: Thu Jun 25 15:44:08 2026 +0800
Added show create pipe/database/topic (#17702)
* ut
* show create
* fix
* Update IoTDBDatabaseIT.java
* Update IoTDBSubscriptionTopicIT.java
* Remove tree model show create topic syntax
* Address show create review comments
* Fixed
---
.github/scripts/package-client-cpp-manylinux228.sh | 0
.../relational/it/schema/IoTDBDatabaseIT.java | 60 ++++++
.../dual/tablemodel/IoTDBSubscriptionTopicIT.java | 27 +++
.../apache/iotdb/db/i18n/DataNodePipeMessages.java | 6 +
.../iotdb/db/i18n/DataNodeQueryMessages.java | 1 +
.../iotdb/db/i18n/DataNodeSchemaMessages.java | 2 +
.../apache/iotdb/db/i18n/DataNodePipeMessages.java | 4 +
.../iotdb/db/i18n/DataNodeQueryMessages.java | 1 +
.../iotdb/db/i18n/DataNodeSchemaMessages.java | 2 +
.../common/header/DatasetHeaderFactory.java | 12 ++
.../iotdb/db/queryengine/plan/Coordinator.java | 2 +
.../execution/config/TableConfigTaskVisitor.java | 65 ++++++
.../execution/config/TreeConfigTaskVisitor.java | 6 +
.../config/executor/ClusterConfigTaskExecutor.java | 156 +++++++++++++-
.../config/executor/IConfigTaskExecutor.java | 6 +
.../relational/ShowCreateDatabaseTask.java | 96 +++++++++
.../metadata/relational/ShowCreatePipeTask.java | 186 ++++++++++++++++
.../sys/subscription/ShowCreateTopicTask.java | 116 ++++++++++
.../relational/analyzer/StatementAnalyzer.java | 18 ++
.../plan/relational/sql/ast/AstVisitor.java | 12 ++
.../relational/sql/ast/ShowCreateDatabase.java | 92 ++++++++
.../plan/relational/sql/ast/ShowCreatePipe.java | 84 ++++++++
.../plan/relational/sql/ast/ShowCreateTopic.java | 84 ++++++++
.../plan/relational/sql/parser/AstBuilder.java | 21 ++
.../relational/sql/util/DataNodeSqlFormatter.java | 29 +++
.../metadata/relational/ShowCreateTaskTest.java | 234 +++++++++++++++++++++
.../plan/relational/sql/ShowCreateTopicTest.java | 73 +++++++
.../pipe/config/constant/SystemConstant.java | 6 +
.../schema/column/ColumnHeaderConstant.java | 19 ++
.../db/relational/grammar/sql/RelationalSql.g4 | 15 ++
30 files changed, 1432 insertions(+), 3 deletions(-)
diff --git a/.github/scripts/package-client-cpp-manylinux228.sh
b/.github/scripts/package-client-cpp-manylinux228.sh
old mode 100755
new mode 100644
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 dac15d8b66b..31cd0241f69 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
@@ -293,6 +293,66 @@ 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,
max_schema_region_group_num=DEFAULT, max_data_region_group_num=DEFAULT,
time_partition_interval=100000)");
+
+ try (final ResultSet resultSet =
+ statement.executeQuery("show create database test_show_create_db")) {
+ assertTrue(resultSet.next());
+ assertEquals("test_show_create_db", resultSet.getString("Database"));
+ final String createDatabaseSQL = resultSet.getString("Create
Database");
+ assertTrue(
+ createDatabaseSQL,
+ createDatabaseSQL.startsWith("CREATE DATABASE
\"test_show_create_db\" WITH ("));
+ assertTrue(createDatabaseSQL, createDatabaseSQL.contains("ttl=300"));
+ assertTrue(createDatabaseSQL,
createDatabaseSQL.contains("time_partition_interval=100000"));
+ assertTrue(createDatabaseSQL,
createDatabaseSQL.contains("max_schema_region_group_num="));
+ assertTrue(createDatabaseSQL,
createDatabaseSQL.contains("max_data_region_group_num="));
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @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()) {
+ assertShowCreateSystemDatabaseFails(statement, "information_schema");
+ assertShowCreateSystemDatabaseFails(statement, "__audit");
+ }
+ }
+
+ private static void assertShowCreateSystemDatabaseFails(
+ final Statement statement, final String database) throws SQLException {
+ try {
+ statement.executeQuery("show create database " + database);
+ fail("show create database " + database + " 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/integration-test/src/test/java/org/apache/iotdb/subscription/it/dual/tablemodel/IoTDBSubscriptionTopicIT.java
b/integration-test/src/test/java/org/apache/iotdb/subscription/it/dual/tablemodel/IoTDBSubscriptionTopicIT.java
index c71a7b2319b..068c2ad69ce 100644
---
a/integration-test/src/test/java/org/apache/iotdb/subscription/it/dual/tablemodel/IoTDBSubscriptionTopicIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/subscription/it/dual/tablemodel/IoTDBSubscriptionTopicIT.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.it.utils.TestUtils;
import org.apache.iotdb.isession.ITableSession;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
import
org.apache.iotdb.itbase.category.MultiClusterIT2SubscriptionTableArchVerification;
+import org.apache.iotdb.itbase.env.BaseEnv;
import org.apache.iotdb.pipe.it.dual.tablemodel.TableModelUtils;
import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.subscription.config.TopicConstant;
@@ -52,6 +53,9 @@ import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
@@ -100,6 +104,29 @@ public class IoTDBSubscriptionTopicIT extends
AbstractSubscriptionDualIT {
.setIsPipeEnableMemoryCheck(false);
}
+ @Ignore
+ @Test
+ public void testShowCreateTopic() throws Exception {
+ TableModelUtils.createDataBaseAndTable(
+ senderEnv, "test_show_create_topic_db",
"test_show_create_topic_table");
+
+ try (final Connection connection =
senderEnv.getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ final Statement statement = connection.createStatement()) {
+ statement.execute(
+ "create topic test_show_create_topic with
('database'='test_show_create_topic_db','table'='test_show_create_topic_table','format'='"
+ + TopicConstant.FORMAT_TS_FILE_VALUE
+ + "')");
+
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show create topic test_show_create_topic"),
+ "Topic,Create Topic,",
+ Collections.singleton(
+ "test_show_create_topic,CREATE TOPIC \"test_show_create_topic\"
WITH ('database'='test_show_create_topic_db','format'='"
+ + TopicConstant.FORMAT_TS_FILE_VALUE
+ + "','table'='test_show_create_topic_table'),"));
+ }
+ }
+
@Ignore
@Test
public void testTabletTopicWithPath() throws Exception {
diff --git
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
index 0d1059d90b6..050de467f26 100644
---
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
@@ -131,6 +131,8 @@ public final class DataNodePipeMessages {
"Failed to decrease reference count for event {} in
PipeRealtimePriorityBlockingQueue";
public static final String FAILED_TO_GET_PENDINGQUEUE_NO_SUCH_SUBTASK =
"Failed to get PendingQueue. No such subtask: ";
+ public static final String FAILED_TO_GET_PIPE_INFO_FROM_CONFIG_NODE_STATUS =
+ "Failed to get pipe info from config node, status is %s.";
public static final String FAILED_TO_GET_PIPE_METAS_WILL_BE =
"Failed to get pipe metas, will be synced by configNode later...";
public static final String FAILED_TO_GET_PIPE_PLUGIN_JAR_FROM =
@@ -224,6 +226,10 @@ public final class DataNodePipeMessages {
"Pipe skipping temporary TsFile which shouldn't be transferred: {}";
public static final String PULLED_PIPE_META_FROM_CONFIG_NODE_RECOVERING =
"Pulled pipe meta from config node: {}, recovering ...";
+ public static final String FAILED_TO_SHOW_CREATE_PIPE_NOT_EXIST =
+ "Failed to show create pipe %s, the pipe does not exist.";
+ public static final String FAILED_TO_SHOW_CREATE_TOPIC_NOT_EXIST =
+ "Failed to show create topic %s, the topic does not exist.";
public static final String RECEIVED_PIPE_HEARTBEAT_REQUEST_FROM_CONFIG_NODE =
"Received pipe heartbeat request {} from config node.";
public static final String
REGION_NO_TSFILEINSERTIONEVENTS_TO_REPLACE_FOR_SOURCE =
diff --git
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index 4208b0ae18c..f870290c09a 100644
---
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -301,6 +301,7 @@ public final class DataNodeQueryMessages {
"select into: the i of ${i} should be an integer.";
public static final String FAILED_TO_GET_DATABASE_MAP =
"Failed to get database Map";
+ public static final String UNKNOWN_DATABASE = "Unknown database %s";
public static final String
LOAD_ANALYSIS_STAGE_ALL_TSFILES_HAVE_BEEN_ANALYZED =
"Load - Analysis Stage: all tsfiles have been analyzed.";
public static final String ASYNC_LOAD_HAS_FAILED_AND_IS_NOW_TRYING =
diff --git
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
index 9574ca9bc8a..2b5fe9d72f6 100644
---
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
@@ -396,6 +396,8 @@ public final class DataNodeSchemaMessages {
public static final String SYSTEM_VIEW_NOT_SUPPORT_SHOW_CREATE =
"The system view does not support show create.";
+ public static final String SYSTEM_DATABASE_NOT_SUPPORT_SHOW_CREATE =
+ "The system database does not support show create.";
// ======================== Traverser ========================
diff --git
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
index 13369260db0..147d977d572 100644
---
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodePipeMessages.java
@@ -217,6 +217,10 @@ public final class DataNodePipeMessages {
"Pipe 跳过不应传输的临时 TsFile:{}";
public static final String PULLED_PIPE_META_FROM_CONFIG_NODE_RECOVERING =
"已从 config node 拉取 pipe 元数据:{},正在恢复 ...";
+ public static final String FAILED_TO_SHOW_CREATE_PIPE_NOT_EXIST =
+ "show create pipe %s 失败,该 pipe 不存在。";
+ public static final String FAILED_TO_SHOW_CREATE_TOPIC_NOT_EXIST =
+ "show create topic %s 失败,该 topic 不存在。";
public static final String RECEIVED_PIPE_HEARTBEAT_REQUEST_FROM_CONFIG_NODE =
"收到来自 config node 的 pipe 心跳请求 {}。";
public static final String
REGION_NO_TSFILEINSERTIONEVENTS_TO_REPLACE_FOR_SOURCE =
diff --git
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index e966de43ead..b0dae59e198 100644
---
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -299,6 +299,7 @@ public final class DataNodeQueryMessages {
"SELECT INTO:${i} 中的 i 应为整数。";
public static final String FAILED_TO_GET_DATABASE_MAP =
"获取数据库映射失败";
+ public static final String UNKNOWN_DATABASE = "未知数据库 %s";
public static final String
LOAD_ANALYSIS_STAGE_ALL_TSFILES_HAVE_BEEN_ANALYZED =
"加载 - 分析阶段:所有 TsFile 已分析完毕。";
public static final String ASYNC_LOAD_HAS_FAILED_AND_IS_NOW_TRYING =
diff --git
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
index 77370266409..de8b762c10b 100644
---
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java
@@ -395,6 +395,8 @@ public final class DataNodeSchemaMessages {
public static final String SYSTEM_VIEW_NOT_SUPPORT_SHOW_CREATE =
"系统视图不支持 show create。";
+ public static final String SYSTEM_DATABASE_NOT_SUPPORT_SHOW_CREATE =
+ "系统数据库不支持 show create。";
// ======================== 附加 SchemaRegion 相关消息 ========================
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..c2a1a9f02d1 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,18 @@ public class DatasetHeaderFactory {
return new
DatasetHeader(ColumnHeaderConstant.showCreateTableColumnHeaders, true);
}
+ public static DatasetHeader getShowCreatePipeColumnHeader() {
+ return new DatasetHeader(ColumnHeaderConstant.showCreatePipeColumnHeaders,
true);
+ }
+
+ public static DatasetHeader getShowCreateTopicColumnHeader() {
+ return new
DatasetHeader(ColumnHeaderConstant.showCreateTopicColumnHeaders, 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/Coordinator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
index 73a09597cd5..4a552ddbeb0 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
@@ -128,6 +128,7 @@ 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.ShowCurrentDatabase;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentSqlDialect;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCurrentTimestamp;
@@ -623,6 +624,7 @@ public class Coordinator {
if (statement instanceof DropDB
|| statement instanceof CountDB
|| statement instanceof ShowDB
+ || statement instanceof ShowCreateDatabase
|| statement instanceof CreateDB
|| statement instanceof AlterDB
|| statement instanceof Use
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 20f484e10d7..54ddb4ebd9d 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
@@ -111,6 +111,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;
@@ -144,6 +146,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.Al
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.CreateTopicTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.DropSubscriptionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.DropTopicTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowCreateTopicTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowSubscriptionsTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowTopicsTask;
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analyzer;
@@ -213,6 +216,9 @@ 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.ShowCreateTopic;
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;
@@ -429,6 +435,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());
+ }
+
@Override
public IConfigTask visitCountDB(final CountDB node, final MPPQueryContext
context) {
context.setQueryType(QueryType.READ);
@@ -1203,6 +1218,8 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
PipeSourceConstant.SOURCE_IOTDB_USERNAME_KEY,
userEntity.getUsername());
replacedSourceAttributes.put(
PipeSourceConstant.SOURCE_IOTDB_CLI_HOSTNAME,
userEntity.getCliHostname());
+ replacedSourceAttributes.put(
+ SystemConstant.SOURCE_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
} else if (!sourceParameters.hasAnyAttributes(
PipeSourceConstant.EXTRACTOR_IOTDB_PASSWORD_KEY,
PipeSourceConstant.SOURCE_IOTDB_PASSWORD_KEY)) {
@@ -1272,6 +1289,8 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
connectorAttributes.put(PipeSinkConstant.SINK_IOTDB_USERNAME_KEY,
userEntity.getUsername());
connectorAttributes.put(
PipeSinkConstant.SINK_IOTDB_CLI_HOSTNAME,
userEntity.getCliHostname());
+ connectorAttributes.put(
+ SystemConstant.SINK_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
} else if (!connectorParameters.hasAnyAttributes(
PipeSinkConstant.CONNECTOR_IOTDB_PASSWORD_KEY,
PipeSinkConstant.SINK_IOTDB_PASSWORD_KEY)) {
throw new SemanticException(
@@ -1314,6 +1333,8 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
extractorAttributes,
new UserEntity(context.getUserId(), context.getUsername(),
context.getCliHostname()),
true);
+ } else {
+ markSourceAuthenticationAsExplicitIfNecessary(extractorAttributes);
}
mayChangeSourcePattern(extractorAttributes);
@@ -1323,11 +1344,42 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
node.getConnectorAttributes(),
new UserEntity(context.getUserId(), context.getUsername(),
context.getCliHostname()),
true);
+ } else {
+
markSinkAuthenticationAsExplicitIfNecessary(node.getConnectorAttributes());
}
return new AlterPipeTask(node, userName);
}
+ public static void markSourceAuthenticationAsExplicitIfNecessary(
+ final Map<String, String> sourceAttributes) {
+ final PipeParameters sourceParameters = new
PipeParameters(sourceAttributes);
+ if (sourceParameters.hasAnyAttributes(
+ PipeSourceConstant.EXTRACTOR_IOTDB_USER_KEY,
+ PipeSourceConstant.SOURCE_IOTDB_USER_KEY,
+ PipeSourceConstant.EXTRACTOR_IOTDB_USERNAME_KEY,
+ PipeSourceConstant.SOURCE_IOTDB_USERNAME_KEY,
+ PipeSourceConstant.EXTRACTOR_IOTDB_PASSWORD_KEY,
+ PipeSourceConstant.SOURCE_IOTDB_PASSWORD_KEY)) {
+ sourceAttributes.put(
+ SystemConstant.SOURCE_AUTHENTICATION_INJECTED_KEY,
Boolean.FALSE.toString());
+ }
+ }
+
+ public static void markSinkAuthenticationAsExplicitIfNecessary(
+ final Map<String, String> sinkAttributes) {
+ final PipeParameters sinkParameters = new PipeParameters(sinkAttributes);
+ if (sinkParameters.hasAnyAttributes(
+ PipeSinkConstant.CONNECTOR_IOTDB_USER_KEY,
+ PipeSinkConstant.SINK_IOTDB_USER_KEY,
+ PipeSinkConstant.CONNECTOR_IOTDB_USERNAME_KEY,
+ PipeSinkConstant.SINK_IOTDB_USERNAME_KEY,
+ PipeSinkConstant.CONNECTOR_IOTDB_PASSWORD_KEY,
+ PipeSinkConstant.SINK_IOTDB_PASSWORD_KEY)) {
+ sinkAttributes.put(SystemConstant.SINK_AUTHENTICATION_INJECTED_KEY,
Boolean.FALSE.toString());
+ }
+ }
+
@Override
public IConfigTask visitDropPipe(DropPipe node, MPPQueryContext context) {
context.setQueryType(QueryType.OTHER);
@@ -1355,6 +1407,19 @@ 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 visitShowCreateTopic(ShowCreateTopic node,
MPPQueryContext context) {
+ context.setQueryType(QueryType.READ);
+ accessControl.checkUserGlobalSysPrivilege(context);
+ return new ShowCreateTopicTask(node);
+ }
+
@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/TreeConfigTaskVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
index 28745712d22..78a0da4dfb5 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
@@ -243,6 +243,8 @@ import static
org.apache.iotdb.commons.executable.ExecutableManager.getUnTrusted
import static
org.apache.iotdb.commons.executable.ExecutableManager.isUriTrusted;
import static
org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor.checkAndEnrichSinkUser;
import static
org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor.checkAndEnrichSourceUser;
+import static
org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor.markSinkAuthenticationAsExplicitIfNecessary;
+import static
org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor.markSourceAuthenticationAsExplicitIfNecessary;
public class TreeConfigTaskVisitor extends StatementVisitor<IConfigTask,
MPPQueryContext> {
@@ -698,6 +700,8 @@ public class TreeConfigTaskVisitor extends
StatementVisitor<IConfigTask, MPPQuer
sourceAttributes,
new UserEntity(context.getUserId(), context.getUsername(),
context.getCliHostname()),
true);
+ } else {
+ markSourceAuthenticationAsExplicitIfNecessary(sourceAttributes);
}
if (alterPipeStatement.isReplaceAllSinkAttributes()) {
@@ -706,6 +710,8 @@ public class TreeConfigTaskVisitor extends
StatementVisitor<IConfigTask, MPPQuer
alterPipeStatement.getSinkAttributes(),
context.getSession().getUserEntity(),
true);
+ } else {
+
markSinkAuthenticationAsExplicitIfNecessary(alterPipeStatement.getSinkAttributes());
}
return new AlterPipeTask(alterPipeStatement);
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 6eda402c2eb..420c3c8285f 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,8 @@ 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.Audit;
+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;
@@ -119,6 +121,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;
@@ -137,6 +140,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TDropTriggerReq;
import org.apache.iotdb.confignode.rpc.thrift.TExtendRegionReq;
import org.apache.iotdb.confignode.rpc.thrift.TFetchTableResp;
import org.apache.iotdb.confignode.rpc.thrift.TGetAllPipeInfoResp;
+import org.apache.iotdb.confignode.rpc.thrift.TGetAllTopicInfoResp;
import org.apache.iotdb.confignode.rpc.thrift.TGetDatabaseReq;
import org.apache.iotdb.confignode.rpc.thrift.TGetPipePluginTableResp;
import org.apache.iotdb.confignode.rpc.thrift.TGetRegionIdReq;
@@ -163,6 +167,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;
@@ -184,7 +189,9 @@ import org.apache.iotdb.db.exception.StorageEngineException;
import org.apache.iotdb.db.exception.ainode.AINodeConnectionException;
import org.apache.iotdb.db.exception.metadata.PathNotExistException;
import org.apache.iotdb.db.exception.metadata.SchemaQuotaExceededException;
+import org.apache.iotdb.db.i18n.DataNodePipeMessages;
import org.apache.iotdb.db.i18n.DataNodeQueryMessages;
+import org.apache.iotdb.db.i18n.DataNodeSchemaMessages;
import org.apache.iotdb.db.pipe.agent.PipeDataNodeAgent;
import org.apache.iotdb.db.pipe.source.dataregion.DataRegionListeningFilter;
import org.apache.iotdb.db.protocol.client.ConfigNodeClient;
@@ -234,6 +241,8 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational
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;
@@ -252,6 +261,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.TestConnectionT
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.pipe.ShowPipeTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.quota.ShowSpaceQuotaTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.quota.ShowThrottleQuotaTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowCreateTopicTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowSubscriptionsTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowTopicsTask;
import org.apache.iotdb.db.queryengine.plan.expression.Expression;
@@ -2362,7 +2372,7 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
future.setException(
new IoTDBException(
String.format(
- "Failed to get pipe info from config node, status is %s.",
+
DataNodePipeMessages.FAILED_TO_GET_PIPE_INFO_FROM_CONFIG_NODE_STATUS,
getAllPipeInfoResp.getStatus()),
TSStatusCode.PIPE_ERROR.getStatusCode()));
return future;
@@ -2744,6 +2754,66 @@ 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);
+ }
+ // showPipe applies user visibility; getAllPipeInfo is needed for full
pipe attributes.
+ final TShowPipeResp visiblePipeResp =
configNodeClient.showPipe(tShowPipeReq);
+ if (visiblePipeResp.getStatus().getCode() !=
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ future.setException(new IoTDBException(visiblePipeResp.getStatus()));
+ return future;
+ }
+ if (!visiblePipeResp.isSetPipeInfoList() ||
visiblePipeResp.getPipeInfoList().isEmpty()) {
+ future.setException(
+ new IoTDBException(
+
String.format(DataNodePipeMessages.FAILED_TO_SHOW_CREATE_PIPE_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(
+
DataNodePipeMessages.FAILED_TO_GET_PIPE_INFO_FROM_CONFIG_NODE_STATUS,
+ 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(DataNodePipeMessages.FAILED_TO_SHOW_CREATE_PIPE_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) {
@@ -2973,6 +3043,44 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
return future;
}
+ @Override
+ public SettableFuture<ConfigTaskResult> showCreateTopic(final String
topicName) {
+ if (!SubscriptionConfig.getInstance().getSubscriptionEnabled()) {
+ return SUBSCRIPTION_NOT_ENABLED_ERROR_FUTURE;
+ }
+
+ final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ try (final ConfigNodeClient configNodeClient =
+
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+ final TGetAllTopicInfoResp getAllTopicInfoResp =
configNodeClient.getAllTopicInfo();
+ if (getAllTopicInfoResp.getStatus().getCode()
+ != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ future.setException(new
IoTDBException(getAllTopicInfoResp.getStatus()));
+ return future;
+ }
+
+ final TopicMeta topicMeta =
+ getAllTopicInfoResp.getAllTopicInfo().stream()
+ .map(TopicMeta::deserialize)
+ .filter(meta -> meta.visibleUnder(true) &&
meta.getTopicName().equals(topicName))
+ .findFirst()
+ .orElse(null);
+ if (topicMeta == null) {
+ future.setException(
+ new IoTDBException(
+ String.format(
+
DataNodePipeMessages.FAILED_TO_SHOW_CREATE_TOPIC_NOT_EXIST, topicName),
+ TSStatusCode.TOPIC_NOT_EXIST_ERROR.getStatusCode()));
+ return future;
+ }
+
+ ShowCreateTopicTask.buildTsBlock(topicMeta, future);
+ } catch (final Exception e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
@Override
public SettableFuture<ConfigTaskResult> alterEncodingCompressor(
final String queryId,
@@ -4193,6 +4301,47 @@ 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)
+ || Audit.TABLE_MODEL_AUDIT_DATABASE.equalsIgnoreCase(database)) {
+ future.setException(
+ new IoTDBException(
+ DataNodeSchemaMessages.SYSTEM_DATABASE_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(DataNodeQueryMessages.UNKNOWN_DATABASE,
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
@@ -4226,7 +4375,7 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
} else {
future.setException(
new IoTDBException(
- String.format("Unknown database %s", database),
+ String.format(DataNodeQueryMessages.UNKNOWN_DATABASE,
database),
TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()));
unsetDatabaseIfNotExist(useDB.getDatabaseId().getValue(),
clientSession);
}
@@ -5000,7 +5149,8 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
private String getTableErrorMessage(final TSStatus status, final String
database) {
if (status.code == TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()) {
unsetDatabaseIfNotExist(database,
SessionManager.getInstance().getCurrSession());
- return String.format("Unknown database %s",
PathUtils.unQualifyDatabaseName(database));
+ return String.format(
+ DataNodeQueryMessages.UNKNOWN_DATABASE,
PathUtils.unQualifyDatabaseName(database));
}
return status.getMessage();
}
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 4e551983d73..07f1a30fb19 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
@@ -236,6 +236,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showPipes(
ShowPipesStatement showPipesStatement, String userName);
+ SettableFuture<ConfigTaskResult> showCreatePipe(String pipeName, String
userName);
+
SettableFuture<ConfigTaskResult> showSubscriptions(
ShowSubscriptionsStatement showSubscriptionsStatement);
@@ -250,6 +252,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showTopics(ShowTopicsStatement
showTopicsStatement);
+ SettableFuture<ConfigTaskResult> showCreateTopic(String topicName);
+
SettableFuture<ConfigTaskResult> alterEncodingCompressor(
String queryId, AlterEncodingCompressorStatement
alterEncodingCompressorStatement);
@@ -340,6 +344,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> countDatabases(
final CountDB countDB, final Predicate<String> canSeeDB);
+ 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..590d6fd30a0
--- /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(",max_schema_region_group_num=")
+ .append(databaseInfo.getMaxSchemaRegionNum())
+ .append(",max_data_region_group_num=")
+ .append(databaseInfo.getMaxDataRegionNum())
+ .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..80cab3aa004
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreatePipeTask.java
@@ -0,0 +1,186 @@
+/*
+ * 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 boolean hasInjectedSourceAuthentication =
+
Boolean.parseBoolean(source.get(SystemConstant.SOURCE_AUTHENTICATION_INJECTED_KEY));
+ 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 (hasInjectedSourceAuthentication
+ || !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);
+ result.remove(PipeSourceConstant.EXTRACTOR_IOTDB_PASSWORD_KEY);
+ result.remove(PipeSourceConstant.SOURCE_IOTDB_PASSWORD_KEY);
+ }
+ return result;
+ }
+
+ private static Map<String, String> sanitizeSinkAttributes(final Map<String,
String> sink) {
+ final boolean hasInjectedSinkAuthentication =
+
Boolean.parseBoolean(sink.get(SystemConstant.SINK_AUTHENTICATION_INJECTED_KEY));
+ 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 (hasInjectedSinkAuthentication
+ || !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);
+ result.remove(PipeSinkConstant.CONNECTOR_IOTDB_PASSWORD_KEY);
+ result.remove(PipeSinkConstant.SINK_IOTDB_PASSWORD_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/execution/config/sys/subscription/ShowCreateTopicTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/sys/subscription/ShowCreateTopicTask.java
new file mode 100644
index 00000000000..4ab29b026dd
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/sys/subscription/ShowCreateTopicTask.java
@@ -0,0 +1,116 @@
+/*
+ * 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.sys.subscription;
+
+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.commons.subscription.meta.topic.TopicMeta;
+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.db.queryengine.plan.execution.config.metadata.relational.ShowCreateTableTask;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateTopic;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.rpc.subscription.config.ConsumerConstant;
+
+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 ShowCreateTopicTask implements IConfigTask {
+
+ private final String topicName;
+
+ public ShowCreateTopicTask(final ShowCreateTopic showCreateTopic) {
+ this.topicName = showCreateTopic.getTopicName();
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(final IConfigTaskExecutor
configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showCreateTopic(topicName);
+ }
+
+ public static void buildTsBlock(
+ final TopicMeta topicMeta, final SettableFuture<ConfigTaskResult>
future) {
+ final List<TSDataType> outputDataTypes =
+ ColumnHeaderConstant.showCreateTopicColumnHeaders.stream()
+ .map(ColumnHeader::getColumnType)
+ .collect(Collectors.toList());
+
+ final TsBlockBuilder builder = new TsBlockBuilder(outputDataTypes);
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder
+ .getColumnBuilder(0)
+ .writeBinary(new Binary(topicMeta.getTopicName(),
TSFileConfig.STRING_CHARSET));
+ builder
+ .getColumnBuilder(1)
+ .writeBinary(new Binary(getShowCreateTopicSQL(topicMeta),
TSFileConfig.STRING_CHARSET));
+ builder.declarePosition();
+
+ final DatasetHeader datasetHeader =
DatasetHeaderFactory.getShowCreateTopicColumnHeader();
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS,
builder.build(), datasetHeader));
+ }
+
+ public static String getShowCreateTopicSQL(final TopicMeta topicMeta) {
+ final StringBuilder builder =
+ new StringBuilder("CREATE TOPIC ")
+
.append(ShowCreateTableTask.getIdentifier(topicMeta.getTopicName()));
+
+ final Map<String, String> sanitizedAttributes =
+ sanitizeTopicAttributes(topicMeta.getConfig().getAttribute());
+ if (!sanitizedAttributes.isEmpty()) {
+ final List<String> pairs = new ArrayList<>(sanitizedAttributes.size());
+ for (final Map.Entry<String, String> entry :
sanitizedAttributes.entrySet()) {
+ pairs.add(
+ ShowCreateTableTask.getString(entry.getKey())
+ + "="
+ + ShowCreateTableTask.getString(entry.getValue()));
+ }
+ builder.append(" WITH (").append(String.join(",", pairs)).append(")");
+ }
+
+ return builder.toString();
+ }
+
+ private static Map<String, String> sanitizeTopicAttributes(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));
+ result.remove(ConsumerConstant.USERNAME_KEY);
+ result.remove(ConsumerConstant.PASSWORD_KEY);
+ result.remove(ConsumerConstant.ENCRYPTED_PASSWORD_KEY);
+ return result;
+ }
+}
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 5a24cd4f09a..6bc5e2ab4f2 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
@@ -187,6 +187,9 @@ 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.ShowCreateTopic;
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;
@@ -513,6 +516,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);
@@ -4988,6 +4996,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);
@@ -5023,6 +5036,11 @@ public class StatementAnalyzer {
return createAndAssignScope(node, context);
}
+ @Override
+ public Scope visitShowCreateTopic(ShowCreateTopic node, Optional<Scope>
context) {
+ return createAndAssignScope(node, context);
+ }
+
@Override
public Scope visitShowSubscriptions(ShowSubscriptions 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 c00b7f4d492..86084ff2c6a 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 visitCountDB(final CountDB node, final C context) {
return visitStatement(node, context);
}
@@ -319,6 +323,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);
}
@@ -355,6 +363,10 @@ public interface AstVisitor<R, C> extends
CommonQueryAstVisitor<R, C> {
return visitStatement(node, context);
}
+ default R visitShowCreateTopic(ShowCreateTopic node, C context) {
+ return visitStatement(node, context);
+ }
+
default R visitShowSubscriptions(ShowSubscriptions 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/ast/ShowCreateTopic.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreateTopic.java
new file mode 100644
index 00000000000..6f2822c7ec4
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowCreateTopic.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 ShowCreateTopic extends SubscriptionStatement {
+
+ private static final long INSTANCE_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(ShowCreateTopic.class);
+
+ private final String topicName;
+
+ public ShowCreateTopic(final String topicName) {
+ this.topicName = requireNonNull(topicName, "topicName is null");
+ }
+
+ public String getTopicName() {
+ return topicName;
+ }
+
+ @Override
+ public <R, C> R accept(final IAstVisitor<R, C> visitor, final C context) {
+ return ((AstVisitor<R, C>) visitor).visitShowCreateTopic(this, context);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(topicName);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final ShowCreateTopic that = (ShowCreateTopic) obj;
+ return Objects.equals(topicName, that.topicName);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("statement", "SHOW CREATE TOPIC")
+ .add("topicName", topicName)
+ .toString();
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long size = INSTANCE_SIZE;
+ size +=
AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
+ size += RamUsageEstimator.sizeOf(topicName);
+ 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 b3c375129df..bd56b82042d 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
@@ -228,6 +228,9 @@ 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.ShowCreateTopic;
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;
@@ -411,6 +414,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 visitCountDatabasesStatement(
final RelationalSqlParser.CountDatabasesStatementContext ctx) {
@@ -1343,6 +1353,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) {
@@ -1426,6 +1441,12 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
return new ShowTopics(topicName);
}
+ @Override
+ public Node visitShowCreateTopicStatement(
+ RelationalSqlParser.ShowCreateTopicStatementContext ctx) {
+ return new ShowCreateTopic(((Identifier) visit(ctx.topicName)).getValue());
+ }
+
@Override
public Node visitShowSubscriptionsStatement(
RelationalSqlParser.ShowSubscriptionsStatementContext 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 887a6082a5d..28a8dc47138 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;
@@ -62,6 +63,9 @@ 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.ShowCreateTopic;
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;
@@ -146,6 +150,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");
@@ -705,6 +717,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 ");
@@ -819,6 +839,15 @@ public final class DataNodeSqlFormatter extends
CommonQuerySqlFormatter
return null;
}
+ @Override
+ public Void visitShowCreateTopic(ShowCreateTopic node, Integer context) {
+ builder
+ .append("SHOW CREATE TOPIC ")
+ .append(ShowCreateTableTask.getIdentifier(node.getTopicName()));
+
+ return null;
+ }
+
@Override
public Void visitShowSubscriptions(ShowSubscriptions node, Integer context) {
if (Objects.isNull(node.getTopicName())) {
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..bec51507da1
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateTaskTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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.commons.subscription.meta.topic.TopicMeta;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.ShowCreateTopicTask;
+import org.apache.iotdb.rpc.subscription.config.ConsumerConstant;
+
+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.setMaxSchemaRegionNum(0);
+ databaseInfo.setMaxDataRegionNum(1);
+
+ assertEquals(
+ "CREATE DATABASE \"test_db\" WITH (ttl='"
+ + IoTDBConstant.TTL_INFINITE
+ +
"',time_partition_interval=604800000,max_schema_region_group_num=0,max_data_region_group_num=1)",
+ ShowCreateDatabaseTask.getShowCreateDatabaseSQL(databaseInfo));
+ }
+
+ @Test
+ public void testShowCreateDatabaseSQLShouldQuoteIdentifierAndKeepFiniteTTL()
{
+ final TDatabaseInfo databaseInfo = new TDatabaseInfo();
+ databaseInfo.setName("test\"db");
+ databaseInfo.setTTL(123L);
+ databaseInfo.setTimePartitionInterval(1000L);
+ databaseInfo.setMaxSchemaRegionNum(2);
+ databaseInfo.setMaxDataRegionNum(3);
+
+ assertEquals(
+ "CREATE DATABASE \"test\"\"db\" WITH
(ttl=123,time_partition_interval=1000,max_schema_region_group_num=2,max_data_region_group_num=3)",
+ 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_PASSWORD_KEY,
"hashed-password");
+ sourceAttributes.put(PipeSourceConstant.SOURCE_IOTDB_CLI_HOSTNAME, "host");
+ sourceAttributes.put(
+ SystemConstant.SOURCE_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
+
+ 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_PASSWORD_KEY,
"hashed-password");
+ sinkAttributes.put(PipeSinkConstant.SINK_IOTDB_CLI_HOSTNAME, "host");
+ sinkAttributes.put(SystemConstant.SINK_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
+
+ 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
testShowCreatePipeSQLShouldKeepExplicitCredentialsWhenInjectionMarkerIsReset() {
+ 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");
+ sourceAttributes.put(
+ SystemConstant.SOURCE_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
+
+ 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");
+ sinkAttributes.put(SystemConstant.SINK_AUTHENTICATION_INJECTED_KEY,
Boolean.TRUE.toString());
+
+
TableConfigTaskVisitor.markSourceAuthenticationAsExplicitIfNecessary(sourceAttributes);
+
TableConfigTaskVisitor.markSinkAuthenticationAsExplicitIfNecessary(sinkAttributes);
+
+ 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));
+ }
+
+ @Test
+ public void testShowCreateTopicSQLShouldSanitizeInternalAttributes() {
+ final Map<String, String> topicAttributes = new HashMap<>();
+ topicAttributes.put("table", "test_table");
+ topicAttributes.put(SystemConstant.SQL_DIALECT_KEY,
SystemConstant.SQL_DIALECT_TABLE_VALUE);
+ topicAttributes.put("format", "SubscriptionTsFileHandler");
+ topicAttributes.put("database", "test_db");
+ topicAttributes.put("__audit.topic", "audit");
+ topicAttributes.put(ConsumerConstant.USERNAME_KEY, "alice");
+ topicAttributes.put(ConsumerConstant.PASSWORD_KEY, "password");
+ topicAttributes.put(ConsumerConstant.ENCRYPTED_PASSWORD_KEY,
"encrypted-password");
+
+ final TopicMeta topicMeta = new TopicMeta("test_topic", 1L,
topicAttributes);
+
+ assertEquals(
+ "CREATE TOPIC \"test_topic\" WITH
('database'='test_db','format'='SubscriptionTsFileHandler','table'='test_table')",
+ ShowCreateTopicTask.getShowCreateTopicSQL(topicMeta));
+ }
+
+ @Test
+ public void testShowCreateTopicSQLShouldOmitEmptyWithClause() {
+ final Map<String, String> topicAttributes = new HashMap<>();
+ topicAttributes.put(SystemConstant.SQL_DIALECT_KEY,
SystemConstant.SQL_DIALECT_TABLE_VALUE);
+ topicAttributes.put("__audit.topic", "audit");
+
+ final TopicMeta topicMeta = new TopicMeta("test`topic", 1L,
topicAttributes);
+
+ assertEquals(
+ "CREATE TOPIC \"test`topic\"",
ShowCreateTopicTask.getShowCreateTopicSQL(topicMeta));
+ }
+}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ShowCreateTopicTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ShowCreateTopicTest.java
new file mode 100644
index 00000000000..835944596dc
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ShowCreateTopicTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+import org.apache.iotdb.db.protocol.session.IClientSession;
+import org.apache.iotdb.db.protocol.session.InternalClientSession;
+import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
+import org.apache.iotdb.db.queryengine.common.QueryId;
+import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
+import org.apache.iotdb.db.queryengine.plan.relational.analyzer.AnalyzerTest;
+import org.apache.iotdb.db.queryengine.plan.relational.analyzer.TestUtils;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCreateTopic;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.util.DataNodeSqlFormatter;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.time.ZoneId;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class ShowCreateTopicTest {
+
+ private SqlParser sqlParser;
+ private IClientSession clientSession;
+
+ @Before
+ public void setUp() {
+ sqlParser = new SqlParser();
+ clientSession = new InternalClientSession("testClient");
+ clientSession.setDatabaseName("testdb");
+ }
+
+ @Test
+ public void testShowCreateTopicRoundTripWithQuotedIdentifier() {
+ final String sql = "SHOW CREATE TOPIC \"topic-1\"";
+ final Statement statement =
+ sqlParser.createStatement(sql, ZoneId.systemDefault(), clientSession);
+
+ assertTrue(statement instanceof ShowCreateTopic);
+ assertEquals("topic-1", ((ShowCreateTopic) statement).getTopicName());
+ assertEquals(sql, DataNodeSqlFormatter.formatDataNodeSql(statement));
+
+ final Analysis analysis =
+ AnalyzerTest.analyzeSQL(
+ sql,
+ TestUtils.TEST_MATADATA,
+ new MPPQueryContext(
+ sql, new QueryId("show_create_topic_test"),
TestUtils.SESSION_INFO, null, null));
+ assertNotNull(analysis);
+ }
+}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/constant/SystemConstant.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/constant/SystemConstant.java
index bb1210afda7..441c8ca24b7 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/constant/SystemConstant.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/constant/SystemConstant.java
@@ -42,6 +42,10 @@ public class SystemConstant {
public static final String SQL_DIALECT_KEY = "__system.sql-dialect";
public static final String SQL_DIALECT_TREE_VALUE = "tree";
public static final String SQL_DIALECT_TABLE_VALUE = "table";
+ public static final String SOURCE_AUTHENTICATION_INJECTED_KEY =
+ "__system.source-authentication-injected";
+ public static final String SINK_AUTHENTICATION_INJECTED_KEY =
+ "__system.sink-authentication-injected";
/////////////////////////////////// Utility
///////////////////////////////////
@@ -50,6 +54,8 @@ public class SystemConstant {
static {
SYSTEM_KEYS.add(RESTART_OR_NEWLY_ADDED_KEY);
SYSTEM_KEYS.add(SQL_DIALECT_KEY);
+ SYSTEM_KEYS.add(SOURCE_AUTHENTICATION_INJECTED_KEY);
+ SYSTEM_KEYS.add(SINK_AUTHENTICATION_INJECTED_KEY);
}
public static PipeParameters addSystemKeysIfNecessary(final PipeParameters
givenPipeParameters) {
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 33c3fe451ca..d9d6518ac0b 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
@@ -133,6 +133,8 @@ public class ColumnHeaderConstant {
// column names for show topics statement
public static final String TOPIC_NAME = "TopicName";
public static final String TOPIC_CONFIGS = "TopicConfigs";
+ public static final String TOPIC = "Topic";
+ public static final String CREATE_TOPIC = "Create Topic";
// column names for show subscriptions statement
public static final String CONSUMER_GROUP_NAME = "ConsumerGroupName";
@@ -341,6 +343,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";
@@ -610,6 +615,11 @@ public class ColumnHeaderConstant {
new ColumnHeader(TOPIC_NAME, TSDataType.TEXT),
new ColumnHeader(TOPIC_CONFIGS, TSDataType.TEXT));
+ public static final List<ColumnHeader> showCreateTopicColumnHeaders =
+ ImmutableList.of(
+ new ColumnHeader(TOPIC, TSDataType.TEXT),
+ new ColumnHeader(CREATE_TOPIC, TSDataType.TEXT));
+
public static final List<ColumnHeader> showSubscriptionColumnHeaders =
ImmutableList.of(
new ColumnHeader(SUBSCRIPTION_ID, TSDataType.TEXT),
@@ -756,6 +766,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 4222754cdb9..5ae0c5d39e1 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
| countDatabasesStatement
| createDbStatement
| alterDbStatement
@@ -102,6 +103,7 @@ statement
| startPipeStatement
| stopPipeStatement
| showPipesStatement
+ | showCreatePipeStatement
| createPipePluginStatement
| dropPipePluginStatement
| showPipePluginsStatement
@@ -111,6 +113,7 @@ statement
| alterTopicStatement
| dropTopicStatement
| showTopicsStatement
+ | showCreateTopicStatement
| showSubscriptionsStatement
| dropSubscriptionStatement
@@ -205,6 +208,10 @@ showDatabasesStatement
: SHOW DATABASES (DETAILS)?
;
+showCreateDatabaseStatement
+ : SHOW CREATE DATABASE database=identifier
+ ;
+
countDatabasesStatement
: COUNT DATABASES
;
@@ -520,6 +527,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
;
@@ -558,6 +569,10 @@ showTopicsStatement
: SHOW ((TOPIC topicName=identifier) | TOPICS )
;
+showCreateTopicStatement
+ : SHOW CREATE TOPIC topicName=identifier
+ ;
+
showSubscriptionsStatement
: SHOW SUBSCRIPTIONS (ON topicName=identifier)?
;