Skip to content

Commit 61fa8d6

Browse files
authored
Implement schema of 'information_schema' & Make AddLocation plan immune readOnly state
1 parent 96f8c19 commit 61fa8d6

File tree

36 files changed

+612
-288
lines changed

36 files changed

+612
-288
lines changed

integration-test/src/test/java/org/apache/iotdb/pipe/it/tablemodel/IoTDBTablePatternFormatIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ public void testIoTDBPatternWithDataBaseAndTable() throws Exception {
595595
receiverEnv,
596596
"show databases",
597597
"Database,TTL(ms),SchemaReplicationFactor,DataReplicationFactor,TimePartitionInterval,",
598-
Collections.emptySet(),
598+
Collections.singleton("information_schema,INF,null,null,null,"),
599599
(String) null);
600600
}
601601
}

integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBSimpleQueryTableIT.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -611,24 +611,28 @@ public void testUseSameStatement() throws SQLException {
611611

612612
@Test
613613
public void testStorageGroupWithHyphenInName() {
614-
try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
615-
Statement statement = connection.createStatement()) {
614+
try (final Connection connection =
615+
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
616+
final Statement statement = connection.createStatement()) {
616617
statement.setFetchSize(5);
617618
statement.execute("CREATE DATABASE group_with_hyphen");
618619
} catch (SQLException e) {
619620
fail();
620621
}
621622

622-
try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
623-
Statement statement = connection.createStatement()) {
624-
try (ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
623+
try (final Connection connection =
624+
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
625+
final Statement statement = connection.createStatement()) {
626+
try (final ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
625627
while (resultSet.next()) {
626-
StringBuilder builder = new StringBuilder();
628+
final StringBuilder builder = new StringBuilder();
627629
builder.append(resultSet.getString(1));
628-
Assert.assertEquals(builder.toString(), "group_with_hyphen");
630+
Assert.assertTrue(
631+
builder.toString().equals("group_with_hyphen")
632+
|| builder.toString().equals("information_schema"));
629633
}
630634
}
631-
} catch (SQLException e) {
635+
} catch (final SQLException e) {
632636
fail();
633637
}
634638
}

integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@
3737
import java.sql.ResultSetMetaData;
3838
import java.sql.SQLException;
3939
import java.sql.Statement;
40+
import java.util.Arrays;
4041
import java.util.Collections;
42+
import java.util.HashSet;
43+
import java.util.Set;
4144

4245
import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.showDBColumnHeaders;
4346
import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.showDBDetailsColumnHeaders;
@@ -96,6 +99,9 @@ public void testManageDatabase() {
9699
assertEquals(showDBColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
97100
}
98101
while (resultSet.next()) {
102+
if (resultSet.getString(1).equals("information_schema")) {
103+
continue;
104+
}
99105
assertEquals(databaseNames[cnt], resultSet.getString(1));
100106
assertEquals(TTLs[cnt], resultSet.getString(2));
101107
assertEquals(schemaReplicaFactors[cnt], resultSet.getInt(3));
@@ -116,6 +122,9 @@ public void testManageDatabase() {
116122
showDBDetailsColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
117123
}
118124
while (resultSet.next()) {
125+
if (resultSet.getString(1).equals("information_schema")) {
126+
continue;
127+
}
119128
assertEquals(databaseNames[cnt], resultSet.getString(1));
120129
assertEquals(TTLs[cnt], resultSet.getString(2));
121130
assertEquals(schemaReplicaFactors[cnt], resultSet.getInt(3));
@@ -141,6 +150,8 @@ public void testManageDatabase() {
141150
// drop
142151
statement.execute("drop database test");
143152
try (final ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
153+
// Information_schema
154+
assertTrue(resultSet.next());
144155
assertFalse(resultSet.next());
145156
}
146157

@@ -171,6 +182,9 @@ public void testManageDatabase() {
171182
assertEquals(showDBColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
172183
}
173184
while (resultSet.next()) {
185+
if (resultSet.getString(1).equals("information_schema")) {
186+
continue;
187+
}
174188
assertEquals(databaseNames[cnt], resultSet.getString(1));
175189
assertEquals(TTLs[cnt], resultSet.getString(2));
176190
assertEquals(schemaReplicaFactors[cnt], resultSet.getInt(3));
@@ -270,6 +284,9 @@ public void testDatabaseWithSpecificCharacters() throws SQLException {
270284

271285
try (final ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
272286
assertTrue(resultSet.next());
287+
if (resultSet.getString(1).equals("information_schema")) {
288+
assertTrue(resultSet.next());
289+
}
273290
assertEquals("````x", resultSet.getString(1));
274291
assertFalse(resultSet.next());
275292
}
@@ -305,4 +322,87 @@ public void testDatabaseWithSpecificCharacters() throws SQLException {
305322
Collections.singleton("1,4,"));
306323
}
307324
}
325+
326+
@Test
327+
public void testInformationSchema() throws SQLException {
328+
try (final Connection connection =
329+
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
330+
final Statement statement = connection.createStatement()) {
331+
// Test unsupported write plans
332+
final Set<String> writeSQLs =
333+
new HashSet<>(
334+
Arrays.asList(
335+
"create database information_schema",
336+
"drop database information_schema",
337+
"create table information_schema.tableA ()",
338+
"alter table information_schema.tableA add column a id",
339+
"alter table information_schema.tableA set properties ttl=default",
340+
"insert into information_schema.tables (database) values('db')",
341+
"update information_schema.tables set status='RUNNING'"));
342+
343+
for (final String writeSQL : writeSQLs) {
344+
try {
345+
statement.execute(writeSQL);
346+
fail("information_schema does not support write");
347+
} catch (final SQLException e) {
348+
assertEquals(
349+
"701: The database 'information_schema' can only be queried", e.getMessage());
350+
}
351+
}
352+
353+
statement.execute("use information_schema");
354+
355+
TestUtils.assertResultSetEqual(
356+
statement.executeQuery("show databases"),
357+
"Database,TTL(ms),SchemaReplicationFactor,DataReplicationFactor,TimePartitionInterval,",
358+
Collections.singleton("information_schema,INF,null,null,null,"));
359+
TestUtils.assertResultSetEqual(
360+
statement.executeQuery("show tables"),
361+
"TableName,TTL(ms),",
362+
new HashSet<>(
363+
Arrays.asList("databases,INF,", "tables,INF,", "columns,INF,", "queries,INF,")));
364+
365+
TestUtils.assertResultSetEqual(
366+
statement.executeQuery("desc databases"),
367+
"ColumnName,DataType,Category,",
368+
new HashSet<>(
369+
Arrays.asList(
370+
"database,STRING,ID,",
371+
"ttl(ms),STRING,ATTRIBUTE,",
372+
"schema_replication_factor,INT32,ATTRIBUTE,",
373+
"data_replication_factor,INT32,ATTRIBUTE,",
374+
"time_partition_interval,INT64,ATTRIBUTE,",
375+
"model,STRING,ATTRIBUTE,")));
376+
TestUtils.assertResultSetEqual(
377+
statement.executeQuery("desc tables"),
378+
"ColumnName,DataType,Category,",
379+
new HashSet<>(
380+
Arrays.asList(
381+
"database,STRING,ID,",
382+
"table_name,STRING,ID,",
383+
"ttl(ms),STRING,ATTRIBUTE,",
384+
"status,STRING,ATTRIBUTE,")));
385+
TestUtils.assertResultSetEqual(
386+
statement.executeQuery("desc columns"),
387+
"ColumnName,DataType,Category,",
388+
new HashSet<>(
389+
Arrays.asList(
390+
"database,STRING,ID,",
391+
"table_name,STRING,ID,",
392+
"column_name,STRING,ID,",
393+
"datatype,STRING,ATTRIBUTE,",
394+
"category,STRING,ATTRIBUTE,",
395+
"status,STRING,ATTRIBUTE,")));
396+
TestUtils.assertResultSetEqual(
397+
statement.executeQuery("desc queries"),
398+
"ColumnName,DataType,Category,",
399+
new HashSet<>(
400+
Arrays.asList(
401+
"query_id,STRING,ID,",
402+
"start_time,TIMESTAMP,ATTRIBUTE,",
403+
"datanode_id,INT32,ATTRIBUTE,",
404+
"elapsed_time,FLOAT,ATTRIBUTE,",
405+
"statement,STRING,ATTRIBUTE,")));
406+
}
407+
}
308408
}

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/ainode/GetAINodeConfigurationPlan.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@
2222
import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
2323
import org.apache.iotdb.confignode.consensus.request.read.ConfigPhysicalReadPlan;
2424

25-
import java.io.DataOutputStream;
26-
import java.io.IOException;
27-
import java.nio.ByteBuffer;
28-
2925
public class GetAINodeConfigurationPlan extends ConfigPhysicalReadPlan {
3026

3127
// if aiNodeId is set to -1, return all AINode configurations.
@@ -44,17 +40,6 @@ public int getAiNodeId() {
4440
return aiNodeId;
4541
}
4642

47-
@Override
48-
protected void serializeImpl(DataOutputStream stream) throws IOException {
49-
stream.writeShort(getType().getPlanType());
50-
stream.writeInt(aiNodeId);
51-
}
52-
53-
@Override
54-
protected void deserializeImpl(ByteBuffer buffer) throws IOException {
55-
this.aiNodeId = buffer.getInt();
56-
}
57-
5843
@Override
5944
public boolean equals(final Object o) {
6045
if (this == o) {

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/model/GetModelInfoPlan.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
import org.apache.iotdb.confignode.consensus.request.read.ConfigPhysicalReadPlan;
2424
import org.apache.iotdb.confignode.rpc.thrift.TGetModelInfoReq;
2525

26-
import org.apache.tsfile.utils.ReadWriteIOUtils;
27-
28-
import java.io.DataOutputStream;
29-
import java.io.IOException;
30-
import java.nio.ByteBuffer;
3126
import java.util.Objects;
3227

3328
public class GetModelInfoPlan extends ConfigPhysicalReadPlan {
@@ -47,17 +42,6 @@ public String getModelId() {
4742
return modelId;
4843
}
4944

50-
@Override
51-
protected void serializeImpl(DataOutputStream stream) throws IOException {
52-
stream.writeShort(getType().getPlanType());
53-
ReadWriteIOUtils.write(modelId, stream);
54-
}
55-
56-
@Override
57-
protected void deserializeImpl(ByteBuffer buffer) throws IOException {
58-
this.modelId = ReadWriteIOUtils.readString(buffer);
59-
}
60-
6145
@Override
6246
public boolean equals(final Object o) {
6347
if (this == o) {

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/model/ShowModelPlan.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
import org.apache.iotdb.confignode.consensus.request.read.ConfigPhysicalReadPlan;
2424
import org.apache.iotdb.confignode.rpc.thrift.TShowModelReq;
2525

26-
import org.apache.tsfile.utils.ReadWriteIOUtils;
27-
28-
import java.io.DataOutputStream;
29-
import java.io.IOException;
30-
import java.nio.ByteBuffer;
3126
import java.util.Objects;
3227

3328
public class ShowModelPlan extends ConfigPhysicalReadPlan {
@@ -53,21 +48,6 @@ public String getModelName() {
5348
return modelName;
5449
}
5550

56-
@Override
57-
protected void serializeImpl(DataOutputStream stream) throws IOException {
58-
stream.writeShort(getType().getPlanType());
59-
ReadWriteIOUtils.write(modelName != null, stream);
60-
ReadWriteIOUtils.write(modelName, stream);
61-
}
62-
63-
@Override
64-
protected void deserializeImpl(ByteBuffer buffer) throws IOException {
65-
boolean isSetModelId = ReadWriteIOUtils.readBool(buffer);
66-
if (isSetModelId) {
67-
this.modelName = ReadWriteIOUtils.readString(buffer);
68-
}
69-
}
70-
7151
@Override
7252
public boolean equals(final Object o) {
7353
if (this == o) {

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionMetrics.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ private void bindDatabaseRelatedMetrics(AbstractMetricService metricService) {
274274
Metric.DATABASE_NUM.toString(),
275275
MetricLevel.CORE,
276276
clusterSchemaManager,
277-
c -> c.getDatabaseNames(null).size());
277+
// Add 1 for information schema
278+
c -> c.getDatabaseNames(null).size() + 1);
278279

279280
List<String> databases = clusterSchemaManager.getDatabaseNames(null);
280281
for (String database : databases) {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutor.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.RelationalDeleteDataNode;
6767
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.RelationalInsertTabletNode;
6868
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.schema.CreateOrUpdateTableDeviceNode;
69+
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.schema.TableNodeLocationAddNode;
6970
import org.apache.iotdb.db.schemaengine.SchemaEngine;
7071
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
7172
import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager;
@@ -165,7 +166,7 @@ private class WritePlanNodeExecutionVisitor
165166
public RegionExecutionResult visitPlan(
166167
final PlanNode node, final WritePlanNodeExecutionContext context) {
167168

168-
if (CommonDescriptor.getInstance().getConfig().isReadOnly()) {
169+
if (CommonDescriptor.getInstance().getConfig().isReadOnly() && !isForceExecutedPlan(node)) {
169170
return RegionExecutionResult.create(
170171
false,
171172
"Fail to do non-query operations because system is read-only.",
@@ -190,6 +191,10 @@ public RegionExecutionResult visitPlan(
190191
}
191192
}
192193

194+
private boolean isForceExecutedPlan(final PlanNode node) {
195+
return node instanceof TableNodeLocationAddNode;
196+
}
197+
193198
private TSStatus executePlanNodeInConsensusLayer(
194199
final ConsensusGroupId groupId, final PlanNode planNode) throws ConsensusException {
195200
if (groupId instanceof DataRegionId) {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19+
1920
package org.apache.iotdb.db.queryengine.execution.operator.source.relational;
2021

22+
import org.apache.iotdb.commons.schema.table.InformationSchema;
2123
import org.apache.iotdb.db.protocol.session.IClientSession;
2224
import org.apache.iotdb.db.queryengine.plan.Coordinator;
2325
import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
@@ -32,13 +34,12 @@
3234
import java.util.Iterator;
3335
import java.util.List;
3436

35-
import static org.apache.iotdb.commons.schema.table.InformationSchemaTable.QUERIES;
36-
3737
public class InformationSchemaContentSupplierFactory {
3838
private InformationSchemaContentSupplierFactory() {}
3939

40-
public static Iterator<TsBlock> getSupplier(String tableName, List<TSDataType> dataTypes) {
41-
if (tableName.equals(QUERIES.getSchemaTableName())) {
40+
public static Iterator<TsBlock> getSupplier(
41+
final String tableName, final List<TSDataType> dataTypes) {
42+
if (tableName.equals(InformationSchema.QUERIES)) {
4243
return new Iterator<TsBlock>() {
4344
private final TsBlockBuilder resultBuilder = new TsBlockBuilder(dataTypes);
4445
private final ColumnBuilder[] columnBuilders = resultBuilder.getValueColumnBuilders();

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
5252
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
5353
import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
54+
import org.apache.iotdb.db.schemaengine.table.InformationSchemaUtils;
5455
import org.apache.iotdb.db.storageengine.dataregion.modification.DeletionPredicate;
5556
import org.apache.iotdb.db.storageengine.dataregion.modification.IDPredicate;
5657
import org.apache.iotdb.db.storageengine.dataregion.modification.IDPredicate.And;
@@ -342,19 +343,20 @@ public static void analyzeDelete(Delete node, MPPQueryContext queryContext) {
342343
}
343344

344345
@SuppressWarnings("java:S3655") // optional is checked
345-
private static void validateSchema(Delete node, MPPQueryContext queryContext) {
346-
String tableName = node.getTable().getName().getSuffix();
347-
String databaseName;
346+
private static void validateSchema(final Delete node, final MPPQueryContext queryContext) {
347+
final String tableName = node.getTable().getName().getSuffix();
348+
final String databaseName;
348349
if (node.getTable().getName().getPrefix().isPresent()) {
349350
databaseName = node.getTable().getName().getPrefix().get().toString();
350351
} else if (queryContext.getDatabaseName().isPresent()) {
351352
databaseName = queryContext.getDatabaseName().get();
352353
} else {
353354
throw new SemanticException(DATABASE_NOT_SPECIFIED);
354355
}
356+
InformationSchemaUtils.checkDBNameInWrite(databaseName);
355357
node.setDatabaseName(databaseName);
356358

357-
TsTable table = DataNodeTableCache.getInstance().getTable(databaseName, tableName);
359+
final TsTable table = DataNodeTableCache.getInstance().getTable(databaseName, tableName);
358360
if (table == null) {
359361
throw new SemanticException("Table " + tableName + " not found");
360362
}

0 commit comments

Comments
 (0)