This is an automated email from the ASF dual-hosted git repository.
jackietien 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 85524b0e832 Support where condition in show / count devices
85524b0e832 is described below
commit 85524b0e832399bb141b755e6a0e9e5cd9007863
Author: Caideyipi <[email protected]>
AuthorDate: Fri Aug 16 10:33:04 2024 +0800
Support where condition in show / count devices
---
.../relational/it/schema/IoTDBDeviceQueryIT.java | 65 ++++++++++++-
.../operator/schema/SchemaCountOperator.java | 4 +-
.../schema/source/DevicePredicateFilter.java | 51 ++++++++++
.../schema/source/SchemaSourceFactory.java | 21 ++---
.../schema/source/TableDeviceQuerySource.java | 77 ++++++++-------
.../TableModelStatementMemorySourceVisitor.java | 32 +++++--
.../plan/planner/TableOperatorGenerator.java | 50 +++++++---
.../node/metadata/read/TableDeviceFetchNode.java | 6 --
.../metadata/read/TableDeviceQueryCountNode.java | 8 ++
.../relational/analyzer/StatementAnalyzer.java | 92 +++++++++++++++++-
.../schema/CheckSchemaPredicateVisitor.java | 24 +++--
.../schema/ExtractPredicateColumnNameVisitor.java | 11 ++-
.../plan/relational/metadata/MetadataUtil.java | 8 +-
.../metadata/fetcher/SchemaPredicateUtil.java | 5 +-
.../metadata/fetcher/TableDeviceSchemaFetcher.java | 103 +++++++++++++--------
.../plan/relational/planner/LogicalPlanner.java | 66 +++----------
.../distribute/TableModelQueryFragmentPlanner.java | 5 +-
.../TableModelTypeProviderExtractor.java | 24 +++++
.../sql/ast/AbstractQueryDeviceWithCache.java | 103 +++++++++++++++++++++
...ueryDevice.java => AbstractTraverseDevice.java} | 75 +++++++++++----
.../plan/relational/sql/ast/CountDevice.java | 30 +++++-
.../plan/relational/sql/ast/ShowDevice.java | 41 +++++---
.../plan/relational/sql/parser/AstBuilder.java | 14 ++-
.../schemaengine/schemaregion/ISchemaRegion.java | 5 +-
.../schemaregion/impl/SchemaRegionMemoryImpl.java | 9 +-
.../schemaregion/impl/SchemaRegionPBTreeImpl.java | 5 +-
.../mtree/impl/mem/MTreeBelowSGMemoryImpl.java | 31 +------
.../read/resp/info/impl/ShowDevicesResult.java | 18 ++++
.../schemaRegion/SchemaRegionTableDeviceTest.java | 74 ++-------------
.../schemaRegion/SchemaRegionTestUtil.java | 6 +-
.../apache/iotdb/commons/schema/table/TsTable.java | 6 +-
31 files changed, 734 insertions(+), 335 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceQueryIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceQueryIT.java
index 168fbaa715a..ee25eeccd75 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceQueryIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceQueryIT.java
@@ -37,6 +37,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@RunWith(IoTDBTestRunner.class)
@@ -66,6 +67,7 @@ public class IoTDBDeviceQueryIT {
statement.execute(
"insert into table0(region_id, plant_id, device_id, model,
temperature, humidity) values('1', '5', '3', 'A', 37.6, 111.1)");
+ // Test plain show / count
TestUtils.assertResultSetEqual(
statement.executeQuery("show devices from table0"),
"region_id,plant_id,device_id,model,",
@@ -83,18 +85,77 @@ public class IoTDBDeviceQueryIT {
"count(devices),",
Collections.singleton("0,"));
+ // Test show / count with where expression
+ // Test AND
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show devices from table0 where region_id =
'1' and model = 'A'"),
+ "region_id,plant_id,device_id,model,",
+ Collections.singleton("1,5,3,A,"));
+ // Test OR
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery(
+ "count devices from table0 where region_id = '1' or plant_id
like '%'"),
+ "count(devices),",
+ Collections.singleton("1,"));
+ // Test complicated query
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show devices from table0 where region_id <
plant_id"),
+ "region_id,plant_id,device_id,model,",
+ Collections.singleton("1,5,3,A,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("count devices from table0 where region_id <
plant_id"),
+ "count(devices),",
+ Collections.singleton("1,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery(
+ "count devices from table0 where substring(region_id,
cast(plant_id as int32), 1) < plant_id"),
+ "count(devices),",
+ Collections.singleton("1,"));
+ // Test get from cache
+ statement.executeQuery(
+ "select * from table0 where region_id = '1' and plant_id in ('3',
'5') and device_id = '3'");
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery(
+ "show devices from table0 where region_id = '1' and plant_id in
('3', '5') and device_id = '3'"),
+ "region_id,plant_id,device_id,model,",
+ Collections.singleton("1,5,3,A,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery(
+ "count devices from table0 where region_id = '1' and plant_id in
('3', '5') and device_id = '3'"),
+ "count(devices),",
+ Collections.singleton("1,"));
+ // Test filter
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("count devices from table0 where region_id >=
'2'"),
+ "count(devices),",
+ Collections.singleton("0,"));
+
try {
statement.executeQuery("show devices from table2");
fail("Show devices shall fail for non-exist table");
} catch (final Exception e) {
- // Pass
+ assertEquals("701: Table 'test.table2' does not exist.",
e.getMessage());
}
try {
statement.executeQuery("count devices from table2");
fail("Count devices shall fail for non-exist table");
} catch (final Exception e) {
- // Pass
+ assertEquals("701: Table 'test.table2' does not exist.",
e.getMessage());
+ }
+
+ try {
+ statement.executeQuery("show devices from table0 where temperature =
37.6");
+ fail("Show devices shall fail for measurement predicate");
+ } catch (final Exception e) {
+ assertEquals("701: Column 'temperature' cannot be resolved",
e.getMessage());
+ }
+
+ try {
+ statement.executeQuery("count devices from table0 where a = 1");
+ fail("Count devices shall fail for non-exist column");
+ } catch (final Exception e) {
+ assertEquals("701: Column 'a' cannot be resolved", e.getMessage());
}
// Test fully qualified name
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
index 91c7ebda26b..4a0f96a15f4 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
@@ -60,7 +60,9 @@ public class SchemaCountOperator<T extends ISchemaInfo>
implements SourceOperato
private TsBlock next; // next will be set only when done
public SchemaCountOperator(
- PlanNodeId sourceId, OperatorContext operatorContext, ISchemaSource<T>
schemaSource) {
+ final PlanNodeId sourceId,
+ final OperatorContext operatorContext,
+ final ISchemaSource<T> schemaSource) {
this.sourceId = sourceId;
this.operatorContext = operatorContext;
this.schemaSource = schemaSource;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DevicePredicateFilter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DevicePredicateFilter.java
new file mode 100644
index 00000000000..b0a07264337
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DevicePredicateFilter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.execution.operator.schema.source;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.LeafColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.block.TsBlock;
+
+import java.util.List;
+
+public class DevicePredicateFilter {
+ private final List<LeafColumnTransformer> filterLeafColumnTransformerList;
+ private final ColumnTransformer filterOutputTransformer;
+
+ public DevicePredicateFilter(
+ final List<LeafColumnTransformer> filterLeafColumnTransformerList,
+ final ColumnTransformer filterOutputTransformer) {
+ this.filterLeafColumnTransformerList = filterLeafColumnTransformerList;
+ this.filterOutputTransformer = filterOutputTransformer;
+ }
+
+ // Single row tsBlock
+ public boolean match(final TsBlock input) {
+ // feed Filter ColumnTransformer, including TimeStampColumnTransformer and
constant
+ filterLeafColumnTransformerList.forEach(
+ leafColumnTransformer -> leafColumnTransformer.initFromTsBlock(input));
+ filterOutputTransformer.tryEvaluate();
+
+ final Column filterColumn = filterOutputTransformer.getColumn();
+ return !filterColumn.isNull(0) && filterColumn.getBoolean(0);
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
index 66dcbd94436..e72412c5f11 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.path.PathPatternTree;
import org.apache.iotdb.commons.schema.filter.SchemaFilter;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
-import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.INodeSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
@@ -102,20 +101,20 @@ public class SchemaSourceFactory {
}
public static ISchemaSource<IDeviceSchemaInfo> getTableDeviceFetchSource(
- String database,
- String tableName,
- List<Object[]> deviceIdList,
- List<ColumnHeader> columnHeaderList) {
+ final String database,
+ final String tableName,
+ final List<Object[]> deviceIdList,
+ final List<ColumnHeader> columnHeaderList) {
return new TableDeviceFetchSource(database, tableName, deviceIdList,
columnHeaderList);
}
public static ISchemaSource<IDeviceSchemaInfo> getTableDeviceQuerySource(
- String database,
- String tableName,
- List<List<SchemaFilter>> idDeterminedFilterList,
- Expression idFuzzyFilter,
- List<ColumnHeader> columnHeaderList) {
+ final String database,
+ final String tableName,
+ final List<List<SchemaFilter>> idDeterminedFilterList,
+ final List<ColumnHeader> columnHeaderList,
+ final DevicePredicateFilter filter) {
return new TableDeviceQuerySource(
- database, tableName, idDeterminedFilterList, idFuzzyFilter,
columnHeaderList);
+ database, tableName, idDeterminedFilterList, columnHeaderList, filter);
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceQuerySource.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceQuerySource.java
index 13732733503..9a1aeb0e139 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceQuerySource.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceQuerySource.java
@@ -27,22 +27,21 @@ import org.apache.iotdb.commons.schema.table.TsTable;
import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
-import
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.schema.ConvertSchemaPredicateToFilterVisitor;
-import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
-import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl.ShowTableDevicesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.reader.ISchemaReader;
import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
import com.google.common.util.concurrent.ListenableFuture;
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.NoSuchElementException;
import java.util.Objects;
+import java.util.stream.Collectors;
public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo> {
@@ -52,25 +51,20 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
private final List<List<SchemaFilter>> idDeterminedPredicateList;
- private final Expression idFuzzyPredicate;
-
private final List<ColumnHeader> columnHeaderList;
-
- private final TsTable table;
+ private final DevicePredicateFilter filter;
public TableDeviceQuerySource(
final String database,
final String tableName,
final List<List<SchemaFilter>> idDeterminedPredicateList,
- final Expression idFuzzyPredicate,
- final List<ColumnHeader> columnHeaderList) {
+ final List<ColumnHeader> columnHeaderList,
+ final DevicePredicateFilter filter) {
this.database = database;
this.tableName = tableName;
this.idDeterminedPredicateList = idDeterminedPredicateList;
- this.idFuzzyPredicate = idFuzzyPredicate;
this.columnHeaderList = columnHeaderList;
-
- this.table = DataNodeTableCache.getInstance().getTable(database,
tableName);
+ this.filter = filter;
}
@Override
@@ -81,6 +75,9 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
private ISchemaReader<IDeviceSchemaInfo> deviceReader;
private Throwable throwable;
private int index = 0;
+ private final List<TSDataType> dataTypes =
+
columnHeaderList.stream().map(ColumnHeader::getColumnType).collect(Collectors.toList());
+ private IDeviceSchemaInfo next;
@Override
public boolean isSuccess() {
@@ -104,6 +101,16 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
@Override
public boolean hasNext() {
+ while (next == null && innerHasNext()) {
+ final IDeviceSchemaInfo temp = deviceReader.next();
+ if (match(temp)) {
+ next = temp;
+ }
+ }
+ return next != null;
+ }
+
+ private boolean innerHasNext() {
try {
if (throwable != null) {
return false;
@@ -121,11 +128,7 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
}
while (index < devicePatternList.size()) {
- deviceReader =
- schemaRegion.getTableDeviceReader(
- new ShowTableDevicesPlan(
- devicePatternList.get(index),
- getExecutableIdFuzzyFilter(idFuzzyPredicate)));
+ deviceReader =
schemaRegion.getTableDeviceReader(devicePatternList.get(index));
index++;
if (deviceReader.hasNext()) {
return true;
@@ -144,7 +147,18 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
if (!hasNext()) {
throw new NoSuchElementException();
}
- return deviceReader.next();
+ final IDeviceSchemaInfo result = next;
+ next = null;
+ return result;
+ }
+
+ private boolean match(final IDeviceSchemaInfo deviceSchemaInfo) {
+ if (Objects.isNull(filter)) {
+ return true;
+ }
+ final TsBlockBuilder builder = new TsBlockBuilder(dataTypes);
+ transformToTsBlockColumns(deviceSchemaInfo, builder, database);
+ return filter.match(builder.build());
}
@Override
@@ -168,16 +182,6 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
idDeterminedPredicateList);
}
- private SchemaFilter getExecutableIdFuzzyFilter(final Expression
idFuzzyExpression) {
- if (idFuzzyExpression == null) {
- return null;
- }
- final ConvertSchemaPredicateToFilterVisitor visitor =
- new ConvertSchemaPredicateToFilterVisitor();
- return visitor.process(
- idFuzzyExpression, new
ConvertSchemaPredicateToFilterVisitor.Context(table));
- }
-
@Override
public List<ColumnHeader> getInfoQueryColumnHeaders() {
return columnHeaderList;
@@ -186,21 +190,30 @@ public class TableDeviceQuerySource implements
ISchemaSource<IDeviceSchemaInfo>
@Override
public void transformToTsBlockColumns(
final IDeviceSchemaInfo schemaInfo, final TsBlockBuilder builder, final
String database) {
+ transformToTsBlockColumns(schemaInfo, builder, database, tableName,
columnHeaderList, 3);
+ }
+
+ public static void transformToTsBlockColumns(
+ final IDeviceSchemaInfo schemaInfo,
+ final TsBlockBuilder builder,
+ final String database,
+ final String tableName,
+ final List<ColumnHeader> columnHeaderList,
+ int idIndex) {
builder.getTimeColumnBuilder().writeLong(0L);
int resultIndex = 0;
- int idIndex = 0;
final String[] pathNodes = schemaInfo.getRawNodes();
- final TsTable table =
DataNodeTableCache.getInstance().getTable(this.database, tableName);
+ final TsTable table = DataNodeTableCache.getInstance().getTable(database,
tableName);
TsTableColumnSchema columnSchema;
for (final ColumnHeader columnHeader : columnHeaderList) {
columnSchema = table.getColumnSchema(columnHeader.getColumnName());
if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)) {
- if (pathNodes.length <= idIndex + 3 || pathNodes[idIndex + 3] == null)
{
+ if (pathNodes.length <= idIndex || pathNodes[idIndex] == null) {
builder.getColumnBuilder(resultIndex).appendNull();
} else {
builder
.getColumnBuilder(resultIndex)
- .writeBinary(new Binary(pathNodes[idIndex + 3],
TSFileConfig.STRING_CHARSET));
+ .writeBinary(new Binary(pathNodes[idIndex],
TSFileConfig.STRING_CHARSET));
}
idIndex++;
} else if
(columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE)) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
index 4304d8ecf4c..665364b9ef7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
@@ -29,8 +29,10 @@ import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.TableDistributedPlanGenerator;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.TableDistributedPlanner;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.block.TsBlock;
@@ -47,22 +49,22 @@ public class TableModelStatementMemorySourceVisitor
@Override
public StatementMemorySource visitNode(
- Node node, TableModelStatementMemorySourceContext context) {
- DatasetHeader datasetHeader = context.getAnalysis().getRespDatasetHeader();
+ final Node node, final TableModelStatementMemorySourceContext context) {
+ final DatasetHeader datasetHeader =
context.getAnalysis().getRespDatasetHeader();
return new StatementMemorySource(
new TsBlock(0), datasetHeader == null ? EMPTY_HEADER : datasetHeader);
}
@Override
public StatementMemorySource visitExplain(
- Explain node, TableModelStatementMemorySourceContext context) {
+ final Explain node, final TableModelStatementMemorySourceContext
context) {
context.getAnalysis().setStatement(node.getStatement());
- DatasetHeader header =
+ final DatasetHeader header =
new DatasetHeader(
Collections.singletonList(
new ColumnHeader(IoTDBConstant.COLUMN_DISTRIBUTION_PLAN,
TSDataType.TEXT)),
true);
- LogicalQueryPlan logicalPlan =
+ final LogicalQueryPlan logicalPlan =
new
org.apache.iotdb.db.queryengine.plan.relational.planner.LogicalPlanner(
context.getQueryContext(),
LocalExecutionPlanner.getInstance().metadata,
@@ -73,14 +75,14 @@ public class TableModelStatementMemorySourceVisitor
return new StatementMemorySource(new TsBlock(0), header);
}
- // generate table model distributed plan
- TableDistributedPlanGenerator.PlanContext planContext =
+ // Generate table model distributed plan
+ final TableDistributedPlanGenerator.PlanContext planContext =
new TableDistributedPlanGenerator.PlanContext();
- PlanNode outputNodeWithExchange =
+ final PlanNode outputNodeWithExchange =
new TableDistributedPlanner(context.getAnalysis(), logicalPlan,
context.getQueryContext())
.generateDistributedPlanWithOptimize(planContext);
- List<String> lines =
+ final List<String> lines =
outputNodeWithExchange.accept(
new PlanGraphPrinter(),
new PlanGraphPrinter.GraphContext(
@@ -88,4 +90,16 @@ public class TableModelStatementMemorySourceVisitor
return getStatementMemorySource(header, lines);
}
+
+ @Override
+ public StatementMemorySource visitShowDevice(
+ final ShowDevice node, final TableModelStatementMemorySourceContext
context) {
+ return new StatementMemorySource(node.getTsBlock(),
node.getDataSetHeader());
+ }
+
+ @Override
+ public StatementMemorySource visitCountDevice(
+ final CountDevice node, final TableModelStatementMemorySourceContext
context) {
+ return new StatementMemorySource(node.getTsBlock(),
node.getDataSetHeader());
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index 29086a7f6b7..232c5f61d2e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -43,6 +43,7 @@ import
org.apache.iotdb.db.queryengine.execution.operator.process.TableTopKOpera
import
org.apache.iotdb.db.queryengine.execution.operator.schema.CountMergeOperator;
import
org.apache.iotdb.db.queryengine.execution.operator.schema.SchemaCountOperator;
import
org.apache.iotdb.db.queryengine.execution.operator.schema.SchemaQueryScanOperator;
+import
org.apache.iotdb.db.queryengine.execution.operator.schema.source.DevicePredicateFilter;
import
org.apache.iotdb.db.queryengine.execution.operator.schema.source.SchemaSourceFactory;
import
org.apache.iotdb.db.queryengine.execution.operator.sink.IdentitySinkOperator;
import
org.apache.iotdb.db.queryengine.execution.operator.source.AlignedSeriesScanOperator;
@@ -93,11 +94,13 @@ import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -771,42 +774,61 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
@Override
public Operator visitTableDeviceQueryScan(
final TableDeviceQueryScanNode node, final LocalExecutionPlanContext
context) {
- final OperatorContext operatorContext =
+ // Query scan use filterNode directly
+ return new SchemaQueryScanOperator<>(
+ node.getPlanNodeId(),
context
.getDriverContext()
.addOperatorContext(
context.getNextOperatorId(),
node.getPlanNodeId(),
- SchemaQueryScanOperator.class.getSimpleName());
- return new SchemaQueryScanOperator<>(
- node.getPlanNodeId(),
- operatorContext,
+ SchemaQueryScanOperator.class.getSimpleName()),
SchemaSourceFactory.getTableDeviceQuerySource(
node.getDatabase(),
node.getTableName(),
node.getIdDeterminedFilterList(),
- node.getIdFuzzyPredicate(),
- node.getColumnHeaderList()));
+ node.getColumnHeaderList(),
+ null));
}
@Override
public Operator visitTableDeviceQueryCount(
final TableDeviceQueryCountNode node, final LocalExecutionPlanContext
context) {
- final OperatorContext operatorContext =
+ // In "count" we have to reuse filter operator per "next"
+ final List<LeafColumnTransformer> filterLeafColumnTransformerList = new
ArrayList<>();
+ return new SchemaCountOperator<>(
+ node.getPlanNodeId(),
context
.getDriverContext()
.addOperatorContext(
context.getNextOperatorId(),
node.getPlanNodeId(),
- SchemaCountOperator.class.getSimpleName());
- return new SchemaCountOperator<>(
- node.getPlanNodeId(),
- operatorContext,
+ SchemaCountOperator.class.getSimpleName()),
SchemaSourceFactory.getTableDeviceQuerySource(
node.getDatabase(),
node.getTableName(),
node.getIdDeterminedFilterList(),
- node.getIdFuzzyPredicate(),
- node.getColumnHeaderList()));
+ node.getColumnHeaderList(),
+ Objects.nonNull(node.getIdFuzzyPredicate())
+ ? new DevicePredicateFilter(
+ filterLeafColumnTransformerList,
+ new ColumnTransformerBuilder()
+ .process(
+ node.getIdFuzzyPredicate(),
+ new ColumnTransformerBuilder.Context(
+ context
+ .getDriverContext()
+ .getFragmentInstanceContext()
+ .getSessionInfo(),
+ filterLeafColumnTransformerList,
+ makeLayout(Collections.singletonList(node)),
+ new HashMap<>(),
+ ImmutableMap.of(),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ 0,
+ context.getTypeProvider(),
+ metadata)))
+ : null));
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceFetchNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceFetchNode.java
index 435fadacb82..d598a351cb9 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceFetchNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceFetchNode.java
@@ -34,7 +34,6 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.stream.Collectors;
public class TableDeviceFetchNode extends TableDeviceSourceNode {
@@ -75,11 +74,6 @@ public class TableDeviceFetchNode extends
TableDeviceSourceNode {
schemaRegionReplicaSet);
}
- @Override
- public List<String> getOutputColumnNames() {
- return
columnHeaderList.stream().map(ColumnHeader::getColumnName).collect(Collectors.toList());
- }
-
@Override
protected void serializeAttributes(final ByteBuffer byteBuffer) {
PlanNodeType.TABLE_DEVICE_FETCH.serialize(byteBuffer);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceQueryCountNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceQueryCountNode.java
index a631e91b063..b09996bf5bf 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceQueryCountNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TableDeviceQueryCountNode.java
@@ -29,8 +29,11 @@ import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
import java.nio.ByteBuffer;
+import java.util.Collections;
import java.util.List;
+import static
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice.COUNT_DEVICE_HEADER_STRING;
+
public class TableDeviceQueryCountNode extends AbstractTableDeviceQueryNode {
public TableDeviceQueryCountNode(
@@ -51,6 +54,11 @@ public class TableDeviceQueryCountNode extends
AbstractTableDeviceQueryNode {
schemaRegionReplicaSet);
}
+ @Override
+ public List<String> getOutputColumnNames() {
+ return Collections.singletonList(COUNT_DEVICE_HEADER_STRING);
+ }
+
@Override
public <R, C> R accept(final PlanVisitor<R, C> visitor, final C context) {
return visitor.visitTableDeviceQueryCount(this, context);
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 1d7e5bd5abe..7093cbf08dd 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
@@ -19,7 +19,9 @@
package org.apache.iotdb.db.queryengine.plan.relational.analyzer;
+import org.apache.iotdb.commons.schema.table.TsTable;
import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
+import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
import org.apache.iotdb.db.queryengine.common.SessionInfo;
@@ -32,8 +34,12 @@ import
org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.PlannerContext;
import org.apache.iotdb.db.queryengine.plan.relational.planner.ScopeAware;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.TranslationMap;
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AbstractQueryDeviceWithCache;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AddColumn;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AliasedRelation;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AllColumns;
@@ -110,6 +116,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.With;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.WithQuery;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.WrappedInsertStatement;
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertBaseStatement;
+import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
@@ -128,6 +135,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
@@ -1508,7 +1516,7 @@ public class StatementAnalyzer {
analysis.addEmptyColumnReferencesForTable(accessControl,
sessionContext.getIdentity(), name);
ImmutableList.Builder<Field> fields = ImmutableList.builder();
- fields.addAll(analyzeTableOutputFields(table, name, tableSchema.get()));
+ fields.addAll(analyzeTableOutputFields(table.getName(), name,
tableSchema.get()));
// boolean addRowIdColumn = updateKind.isPresent();
//
@@ -1605,14 +1613,16 @@ public class StatementAnalyzer {
}
private List<Field> analyzeTableOutputFields(
- Table table, QualifiedObjectName tableName, TableSchema tableSchema) {
+ final QualifiedName relationAlias,
+ final QualifiedObjectName tableName,
+ final TableSchema tableSchema) {
// TODO: discover columns lazily based on where they are needed (to
support connectors that
// can't enumerate all tables)
ImmutableList.Builder<Field> fields = ImmutableList.builder();
for (ColumnSchema column : tableSchema.getColumns()) {
Field field =
Field.newQualified(
- table.getName(),
+ relationAlias,
Optional.of(column.getName()),
column.getType(),
column.getColumnCategory(),
@@ -2496,15 +2506,87 @@ public class StatementAnalyzer {
@Override
protected Scope visitShowDevice(final ShowDevice node, final
Optional<Scope> context) {
- node.parseQualifiedName(sessionContext);
+ analyzeQueryDevice(node, context);
return null;
}
@Override
protected Scope visitCountDevice(final CountDevice node, final
Optional<Scope> context) {
- node.parseQualifiedName(sessionContext);
+ analyzeQueryDevice(node, context);
return null;
}
+
+ private void analyzeQueryDevice(
+ final AbstractQueryDeviceWithCache node, final Optional<Scope>
context) {
+ node.parseQualifiedName(sessionContext);
+ final String database = node.getDatabase();
+ final String tableName = node.getTableName();
+
+ if (Objects.isNull(database)) {
+ throw new SemanticException("The database must be set before show
devices.");
+ }
+
+ final TsTable table =
DataNodeTableCache.getInstance().getTable(database, tableName);
+
+ if (Objects.isNull(table)) {
+ throw new SemanticException(
+ String.format("Table '%s.%s' does not exist.", database,
tableName));
+ }
+
+ final List<String> attributeList =
+ table.getColumnList().stream()
+ .filter(
+ columnSchema ->
+
columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE))
+ .map(TsTableColumnSchema::getColumnName)
+ .collect(Collectors.toList());
+
+ node.setColumnHeaderList();
+ if (Objects.nonNull(node.getRawExpression())) {
+ final QualifiedObjectName name = new QualifiedObjectName(database,
tableName);
+ final Optional<TableSchema> tableSchema =
metadata.getTableSchema(sessionContext, name);
+ // This can only be a table
+ if (!tableSchema.isPresent()) {
+ throw new SemanticException(String.format("Table '%s' does not
exist", name));
+ }
+
+ final TableSchema originalSchema = tableSchema.get();
+ final ImmutableList.Builder<Field> fields = ImmutableList.builder();
+ fields.addAll(
+ analyzeTableOutputFields(
+ node.getName(),
+ name,
+ new TableSchema(
+ originalSchema.getTableName(),
+ originalSchema.getColumns().stream()
+ .filter(
+ columnSchema ->
+ columnSchema.getColumnCategory() ==
TsTableColumnCategory.ID
+ || columnSchema.getColumnCategory()
+ == TsTableColumnCategory.ATTRIBUTE)
+ .collect(Collectors.toList()))));
+ final List<Field> fieldList = fields.build();
+ final Scope scope = createAndAssignScope(node, context, fieldList);
+ analyzeExpression(node.getRawExpression(), scope);
+ node.setRawExpression(
+ new TranslationMap(
+ Optional.empty(),
+ scope,
+ analysis,
+ fieldList.stream()
+ .map(field -> Symbol.of(field.getName().orElse(null)))
+ .collect(Collectors.toList()),
+ new PlannerContext(metadata, null))
+ .rewrite(node.getRawExpression()));
+ }
+ if (!node.parseRawExpression(table, attributeList, queryContext)) {
+ // Cache hit
+ // Currently we disallow "Or" filter for precise get, thus if it hit
cache
+ // it'll be only one device
+ // TODO: Ensure the disjointness of expressions and allow Or filter
+ analysis.setFinishQueryAfterAnalyze();
+ }
+ }
}
private static boolean hasScopeAsLocalParent(Scope root, Scope parent) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/CheckSchemaPredicateVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/CheckSchemaPredicateVisitor.java
index 379026dbcd4..32db3f51ff0 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/CheckSchemaPredicateVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/CheckSchemaPredicateVisitor.java
@@ -21,6 +21,7 @@ package
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.schem
import org.apache.iotdb.commons.schema.table.TsTable;
import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
+import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
import
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicateVisitor;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BetweenPredicate;
@@ -42,6 +43,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.TableExpressionTy
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Objects;
+
// Return whether input expression can not be bounded to a single ID
public class CheckSchemaPredicateVisitor
extends PredicateVisitor<Boolean, CheckSchemaPredicateVisitor.Context> {
@@ -81,6 +84,10 @@ public class CheckSchemaPredicateVisitor
}
return true;
}
+ // TODO: improve the distinct result set detection logic
+ if (context.isDirectDeviceQuery) {
+ return true;
+ }
return node.getTerms().stream().anyMatch(predicate ->
predicate.accept(this, context));
}
@@ -133,11 +140,11 @@ public class CheckSchemaPredicateVisitor
}
private boolean processColumn(final Expression node, final Context context) {
- return context
- .table
-
.getColumnSchema(node.accept(ExtractPredicateColumnNameVisitor.getInstance(),
null))
- .getColumnCategory()
- .equals(TsTableColumnCategory.ATTRIBUTE);
+ final TsTableColumnSchema schema =
+ context.table.getColumnSchema(
+ node.accept(ExtractPredicateColumnNameVisitor.getInstance(),
null));
+ return Objects.isNull(schema)
+ || schema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE);
}
public static class Context {
@@ -145,10 +152,15 @@ public class CheckSchemaPredicateVisitor
// For query performance analyze
private final MPPQueryContext queryContext;
+ private final boolean isDirectDeviceQuery;
- public Context(final TsTable table, final MPPQueryContext queryContext) {
+ public Context(
+ final TsTable table,
+ final MPPQueryContext queryContext,
+ final boolean isDirectDeviceQuery) {
this.table = table;
this.queryContext = queryContext;
+ this.isDirectDeviceQuery = isDirectDeviceQuery;
}
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/ExtractPredicateColumnNameVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/ExtractPredicateColumnNameVisitor.java
index fb2cc60f619..370c9287723 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/ExtractPredicateColumnNameVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/schema/ExtractPredicateColumnNameVisitor.java
@@ -72,18 +72,25 @@ public class ExtractPredicateColumnNameVisitor extends
PredicateVisitor<String,
final String columnName;
if (node.getLeft() instanceof Literal) {
if (!(node.getRight() instanceof SymbolReference)) {
- throw new IllegalStateException("Can only be SymbolReference, now is "
+ node.getRight());
+ // TODO: implement schema function filter and parse some function call
into id determined
+ // filter
+ return null;
}
columnName = ((SymbolReference) (node.getRight())).getName();
} else {
if (!(node.getLeft() instanceof SymbolReference)) {
- throw new IllegalStateException("Can only be SymbolReference, now is "
+ node.getLeft());
+ return null;
}
columnName = ((SymbolReference) (node.getLeft())).getName();
}
return columnName;
}
+ @Override
+ protected String visitSymbolReference(final SymbolReference node, final Void
context) {
+ return node.getName();
+ }
+
@Override
protected String visitSimpleCaseExpression(final SimpleCaseExpression node,
final Void context) {
return null;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/MetadataUtil.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/MetadataUtil.java
index 3366a48b6b5..2872ea9ea9e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/MetadataUtil.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/MetadataUtil.java
@@ -66,16 +66,16 @@ public class MetadataUtil {
}
public static QualifiedObjectName createQualifiedObjectName(
- SessionInfo session, QualifiedName name) {
+ final SessionInfo session, final QualifiedName name) {
requireNonNull(session, "session is null");
requireNonNull(name, "name is null");
if (name.getParts().size() > 2) {
throw new SemanticException(String.format("Too many dots in table name:
%s", name));
}
- List<String> parts = Lists.reverse(name.getParts());
- String objectName = parts.get(0);
- String databaseName =
+ final List<String> parts = Lists.reverse(name.getParts());
+ final String objectName = parts.get(0);
+ final String databaseName =
(parts.size() > 1)
? parts.get(1)
: session
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
index 1880e92eee9..b470a2465b1 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
@@ -55,12 +55,13 @@ public class SchemaPredicateUtil {
static Pair<List<Expression>, List<Expression>>
separateIdDeterminedPredicate(
final List<Expression> expressionList,
final TsTable table,
- final MPPQueryContext queryContext) {
+ final MPPQueryContext queryContext,
+ final boolean isDirectDeviceQuery) {
final List<Expression> idDeterminedList = new ArrayList<>();
final List<Expression> idFuzzyList = new ArrayList<>();
final CheckSchemaPredicateVisitor visitor = new
CheckSchemaPredicateVisitor();
final CheckSchemaPredicateVisitor.Context context =
- new CheckSchemaPredicateVisitor.Context(table, queryContext);
+ new CheckSchemaPredicateVisitor.Context(table, queryContext,
isDirectDeviceQuery);
for (final Expression expression : expressionList) {
if (expression == null) {
continue;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
index 5e7b1833a76..fa95e78882b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
@@ -39,6 +39,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.schema
import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableDeviceId;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableDeviceSchemaCache;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AbstractTraverseDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FetchDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice;
@@ -168,14 +169,46 @@ public class TableDeviceSchemaFetcher {
final List<String> attributeColumns,
final MPPQueryContext queryContext) {
final List<DeviceEntry> deviceEntryList = new ArrayList<>();
-
+ final ShowDevice statement = new ShowDevice(database, table);
final TsTable tableInstance =
DataNodeTableCache.getInstance().getTable(database, table);
if (tableInstance == null) {
throw new SemanticException(String.format("Table '%s.%s' does not
exist", database, table));
}
+
+ if (parseFilter4TraverseDevice(
+ database,
+ tableInstance,
+ expressionList,
+ statement,
+ deviceEntryList,
+ attributeColumns,
+ queryContext,
+ false)) {
+ fetchMissingDeviceSchemaForQuery(
+ database, tableInstance, attributeColumns, statement,
deviceEntryList, queryContext);
+ }
+
+ // TODO table metadata: implement deduplicate during schemaRegion
execution
+ // TODO table metadata: need further process on input predicates and
transform them into
+ // disjoint sets
+ final Set<DeviceEntry> set = new LinkedHashSet<>(deviceEntryList);
+ return new ArrayList<>(set);
+ }
+
+ // Used by show/count device and update device.
+ // Update device will not access cache
+ public boolean parseFilter4TraverseDevice(
+ final String database,
+ final TsTable tableInstance,
+ final List<Expression> expressionList,
+ final AbstractTraverseDevice statement,
+ final List<DeviceEntry> deviceEntryList,
+ final List<String> attributeColumns,
+ final MPPQueryContext queryContext,
+ final boolean isDirectDeviceQuery) {
final Pair<List<Expression>, List<Expression>> separatedExpression =
SchemaPredicateUtil.separateIdDeterminedPredicate(
- expressionList, tableInstance, queryContext);
+ expressionList, tableInstance, queryContext, isDirectDeviceQuery);
final List<Expression> idDeterminedPredicateList =
separatedExpression.left; // and-concat
final List<Expression> idFuzzyPredicateList = separatedExpression.right;
// and-concat
@@ -220,7 +253,8 @@ public class TableDeviceSchemaFetcher {
index2FilterMapList.get(index),
o -> fuzzyFilter == null || filterVisitor.process(fuzzyFilter, o),
attributeColumns,
- fetchPaths)) {
+ fetchPaths,
+ isDirectDeviceQuery)) {
idSingleMatchPredicateNotInCache.add(index);
}
}
@@ -253,25 +287,15 @@ public class TableDeviceSchemaFetcher {
}
}
}
- fetchMissingDeviceSchemaForQuery(
- database,
- tableInstance,
- attributeColumns,
- idPredicateForFetch,
- compactedIdFuzzyPredicate,
- deviceEntryList,
- fetchPaths,
- queryContext);
+ statement.setIdDeterminedFilterList(idPredicateForFetch);
+ statement.setIdFuzzyPredicate(compactedIdFuzzyPredicate);
+ statement.setPartitionKeyList(fetchPaths);
+ return true;
}
-
- // TODO table metadata: implement deduplicate during schemaRegion
execution
- // TODO table metadata: need further process on input predicates and
transform them into
- // disjoint sets
- final Set<DeviceEntry> set = new LinkedHashSet<>(deviceEntryList);
- return new ArrayList<>(set);
+ return false;
}
- // return whether all of required info of current device is in cache
+ // Return whether all of required info of current device is in cache
private boolean tryGetDeviceInCache(
final List<DeviceEntry> deviceEntryList,
final String database,
@@ -279,7 +303,8 @@ public class TableDeviceSchemaFetcher {
final Map<Integer, List<SchemaFilter>> idFilters,
final Predicate<DeviceEntry> check,
final List<String> attributeColumns,
- final List<IDeviceID> fetchPaths) {
+ final List<IDeviceID> fetchPaths,
+ final boolean isDirectDeviceQuery) {
String[] idValues = new String[tableInstance.getIdNums()];
for (final List<SchemaFilter> schemaFilters : idFilters.values()) {
final IdFilter idFilter = (IdFilter) schemaFilters.get(0);
@@ -290,9 +315,11 @@ public class TableDeviceSchemaFetcher {
idValues = (String[]) truncateTailingNull(idValues);
final Map<String, String> attributeMap =
cache.getDeviceAttribute(database, tableInstance.getTableName(),
idValues);
+
+ final IDeviceID deviceID = convertIdValuesToDeviceID(idValues,
tableInstance);
if (attributeMap == null) {
if (Objects.nonNull(fetchPaths)) {
- fetchPaths.add(convertIdValuesToDeviceID(idValues, tableInstance));
+ fetchPaths.add(deviceID);
}
return false;
}
@@ -301,19 +328,23 @@ public class TableDeviceSchemaFetcher {
if (!attributeMap.containsKey(attributeKey)) {
// The attributes may be updated and the cache entry is stale
if (Objects.nonNull(fetchPaths)) {
- fetchPaths.add(convertIdValuesToDeviceID(idValues, tableInstance));
+ fetchPaths.add(deviceID);
}
return false;
}
attributeValues.add(attributeMap.get(attributeKey));
}
- final DeviceEntry deviceEntry =
- new DeviceEntry(convertIdValuesToDeviceID(idValues, tableInstance),
attributeValues);
+ final DeviceEntry deviceEntry = new DeviceEntry(deviceID, attributeValues);
// TODO table metadata: process cases that selected attr columns different
from those used for
// predicate
if (check.test(deviceEntry)) {
deviceEntryList.add(deviceEntry);
+ // If we partially hit cache in direct device query, we must fetch for
all the predicates
+ // because now we do not support combining memory source and other
sources
+ if (isDirectDeviceQuery) {
+ fetchPaths.add(deviceID);
+ }
}
return true;
}
@@ -331,17 +362,13 @@ public class TableDeviceSchemaFetcher {
final String database,
final TsTable tableInstance,
final List<String> attributeColumns,
- final List<List<SchemaFilter>> idDeterminedFilterList,
- final Expression idFuzzyPredicate,
+ final ShowDevice statement,
final List<DeviceEntry> deviceEntryList,
- final List<IDeviceID> fetchPaths,
final MPPQueryContext mppQueryContext) {
final String table = tableInstance.getTableName();
final long queryId = SessionManager.getInstance().requestQueryId();
- final ShowDevice statement =
- new ShowDevice(database, table, idDeterminedFilterList,
idFuzzyPredicate, fetchPaths);
final ExecutionResult executionResult =
coordinator.executeForTableModel(
statement,
@@ -386,7 +413,7 @@ public class TableDeviceSchemaFetcher {
attributeMap, nodes, 1, columnHeaderList, columns,
tableInstance, i);
nodes = (String[]) truncateTailingNull(nodes);
final IDeviceID deviceID =
IDeviceID.Factory.DEFAULT_FACTORY.create(nodes);
- DeviceEntry deviceEntry =
+ final DeviceEntry deviceEntry =
new DeviceEntry(
deviceID,
attributeColumns.stream().map(attributeMap::get).collect(Collectors.toList()));
@@ -394,7 +421,7 @@ public class TableDeviceSchemaFetcher {
deviceEntryList.add(deviceEntry);
// Only cache those exact device query
// Fetch paths is null iff there are fuzzy queries related to id
columns
- if (Objects.nonNull(fetchPaths)) {
+ if (Objects.nonNull(statement.getPartitionKeyList())) {
cache.put(database, table, Arrays.copyOfRange(nodes, 1,
nodes.length), attributeMap);
}
}
@@ -408,15 +435,15 @@ public class TableDeviceSchemaFetcher {
}
private void constructNodsArrayAndAttributeMap(
- Map<String, String> attributeMap,
- String[] nodes,
+ final Map<String, String> attributeMap,
+ final String[] nodes,
int startIndex,
- List<ColumnHeader> columnHeaderList,
- Column[] columns,
- TsTable tableInstance,
- int rowIndex) {
+ final List<ColumnHeader> columnHeaderList,
+ final Column[] columns,
+ final TsTable tableInstance,
+ final int rowIndex) {
for (int j = 0; j < columnHeaderList.size(); j++) {
- TsTableColumnSchema columnSchema =
+ final TsTableColumnSchema columnSchema =
tableInstance.getColumnSchema(columnHeaderList.get(j).getColumnName());
// means that TsTable tableInstance which previously fetched is
outdated, but it's ok that we
// ignore that newly added column here
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
index 0024d886d83..d5bb6458c9a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
@@ -15,10 +15,7 @@
package org.apache.iotdb.db.queryengine.plan.relational.planner;
import org.apache.iotdb.commons.partition.SchemaPartition;
-import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
-import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
import org.apache.iotdb.commons.utils.TestOnly;
-import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
import org.apache.iotdb.db.queryengine.common.SessionInfo;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
@@ -41,7 +38,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.LogicalOptimizeFactory;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.PlanOptimizer;
-import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AbstractQueryDevice;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AbstractQueryDeviceWithCache;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
@@ -52,21 +49,19 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.WrappedStatement;
import
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
-import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import org.apache.tsfile.enums.TSDataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static java.util.Objects.requireNonNull;
+import static
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice.getDeviceColumnHeaderList;
import static
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager.getTSDataType;
public class LogicalPlanner {
@@ -237,7 +232,7 @@ public class LogicalPlanner {
private PlanNode planFetchDevice(final FetchDevice statement, final Analysis
analysis) {
final List<ColumnHeader> columnHeaderList =
- getColumnHeaderList(statement.getDatabase(), statement.getTableName());
+ getDeviceColumnHeaderList(statement.getDatabase(),
statement.getTableName());
analysis.setRespDatasetHeader(new DatasetHeader(columnHeaderList, true));
@@ -262,22 +257,16 @@ public class LogicalPlanner {
}
private PlanNode planShowDevice(final ShowDevice statement, final Analysis
analysis) {
- final String database = planQueryDevice(statement, analysis);
- List<ColumnHeader> columnHeaderList = null;
- if (!analysis.isFailed()) {
- columnHeaderList = getColumnHeaderList(database,
statement.getTableName());
- analysis.setRespDatasetHeader(
- new DatasetHeader(getColumnHeaderList(database,
statement.getTableName()), true));
- }
+ planQueryDevice(statement, analysis);
final TableDeviceQueryScanNode node =
new TableDeviceQueryScanNode(
queryContext.getQueryId().genPlanNodeId(),
- database,
+ statement.getDatabase(),
statement.getTableName(),
statement.getIdDeterminedFilterList(),
null,
- columnHeaderList,
+ statement.getColumnHeaderList(),
null);
return Objects.nonNull(statement.getIdFuzzyPredicate())
? new FilterNode(
@@ -286,19 +275,16 @@ public class LogicalPlanner {
}
private PlanNode planCountDevice(final CountDevice statement, final Analysis
analysis) {
- final String database = planQueryDevice(statement, analysis);
- final List<ColumnHeader> columnHeaderList =
- Collections.singletonList(new ColumnHeader("count(devices)",
TSDataType.INT64));
- analysis.setRespDatasetHeader(new DatasetHeader(columnHeaderList, true));
+ planQueryDevice(statement, analysis);
final TableDeviceQueryCountNode node =
new TableDeviceQueryCountNode(
queryContext.getQueryId().genPlanNodeId(),
- database,
+ statement.getDatabase(),
statement.getTableName(),
statement.getIdDeterminedFilterList(),
statement.getIdFuzzyPredicate(),
- columnHeaderList,
+ statement.getColumnHeaderList(),
null);
final CountSchemaMergeNode countMergeNode =
@@ -307,15 +293,9 @@ public class LogicalPlanner {
return countMergeNode;
}
- private String planQueryDevice(final AbstractQueryDevice statement, final
Analysis analysis) {
- final String database =
- Objects.isNull(statement.getDatabase())
- ? analysis.getDatabaseName()
- : statement.getDatabase();
-
- if (Objects.isNull(database)) {
- throw new SemanticException("The database must be set before show
devices.");
- }
+ private void planQueryDevice(
+ final AbstractQueryDeviceWithCache statement, final Analysis analysis) {
+ final String database = statement.getDatabase();
final SchemaPartition schemaPartition =
statement.isIdDetermined()
@@ -327,27 +307,9 @@ public class LogicalPlanner {
analysis.setFinishQueryAfterAnalyze();
}
- if (Objects.isNull(
- DataNodeTableCache.getInstance().getTable(database,
statement.getTableName()))) {
- throw new SemanticException(
- String.format("Table '%s.%s' does not exist.", database,
statement.getTableName()));
- }
- return database;
- }
-
- private List<ColumnHeader> getColumnHeaderList(final String database, final
String tableName) {
- final List<TsTableColumnSchema> columnSchemaList =
- DataNodeTableCache.getInstance().getTable(database,
tableName).getColumnList();
-
- final List<ColumnHeader> columnHeaderList = new
ArrayList<>(columnSchemaList.size());
- for (final TsTableColumnSchema columnSchema : columnSchemaList) {
- if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)
- ||
columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE)) {
- columnHeaderList.add(
- new ColumnHeader(columnSchema.getColumnName(),
columnSchema.getDataType()));
- }
+ if (!analysis.isFailed()) {
+ analysis.setRespDatasetHeader(statement.getDataSetHeader());
}
- return columnHeaderList;
}
private enum Stage {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
index 5327a4b690f..b2f8334b4f8 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
@@ -32,6 +32,7 @@ import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.ExchangeNode;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.sink.MultiChildrenSinkNode;
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
@@ -141,7 +142,9 @@ public class TableModelQueryFragmentPlanner {
});
final Statement statement = analysis.getStatement();
- if (statement instanceof Query || statement instanceof ShowDevice) {
+ if (statement instanceof Query
+ || statement instanceof ShowDevice
+ || statement instanceof CountDevice) {
fragmentInstance.getFragment().generateTableModelTypeProvider(queryContext.getTypeProvider());
}
instanceMap.putIfAbsent(fragment.getId(), fragmentInstance);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
index 29fa48400b4..deb6678d4c6 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
@@ -17,6 +17,9 @@ package
org.apache.iotdb.db.queryengine.plan.relational.planner.distribute;
import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.SimplePlanVisitor;
+import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.AbstractTableDeviceQueryNode;
+import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.CountSchemaMergeNode;
+import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.TableDeviceQueryCountNode;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.TableDeviceQueryScanNode;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.ExchangeNode;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.sink.IdentitySinkNode;
@@ -34,12 +37,15 @@ import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNod
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TopKNode;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.type.BooleanType;
import org.apache.tsfile.read.common.type.TypeFactory;
import java.util.HashMap;
import java.util.Map;
+import static
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice.COUNT_DEVICE_HEADER_STRING;
+
public class TableModelTypeProviderExtractor {
private TableModelTypeProviderExtractor() {}
@@ -84,8 +90,26 @@ public class TableModelTypeProviderExtractor {
return null;
}
+ @Override
+ public Void visitCountMerge(final CountSchemaMergeNode node, final Void
context) {
+ beTypeProvider.putTableModelType(
+ new Symbol(COUNT_DEVICE_HEADER_STRING),
TypeFactory.getType(TSDataType.INT64));
+ node.getChildren().forEach(schemaCount -> schemaCount.accept(this,
context));
+ return null;
+ }
+
@Override
public Void visitTableDeviceQueryScan(final TableDeviceQueryScanNode node,
final Void context) {
+ return visitAbstractTableDeviceQueryNode(node);
+ }
+
+ @Override
+ public Void visitTableDeviceQueryCount(
+ final TableDeviceQueryCountNode node, final Void context) {
+ return visitAbstractTableDeviceQueryNode(node);
+ }
+
+ private Void visitAbstractTableDeviceQueryNode(final
AbstractTableDeviceQueryNode node) {
node.getColumnHeaderList()
.forEach(
columnHeader ->
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
new file mode 100644
index 00000000000..94fe965fe4a
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
@@ -0,0 +1,103 @@
+/*
+ * 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.schema.table.TsTable;
+import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
+import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry;
+import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.impl.ShowDevicesResult;
+import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
+
+import org.apache.tsfile.read.common.block.TsBlock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice.getDeviceColumnHeaderList;
+
+public abstract class AbstractQueryDeviceWithCache extends
AbstractTraverseDevice {
+
+ // For query devices fully in cache
+ protected List<ShowDevicesResult> results = new ArrayList<>();
+
+ // The "CountDevice"'s column header list is the same as the device's header
+ // to help reuse filter operator
+ protected List<ColumnHeader> columnHeaderList;
+
+ protected AbstractQueryDeviceWithCache(final QualifiedName name, final
Expression rawExpression) {
+ super(name, rawExpression);
+ }
+
+ protected AbstractQueryDeviceWithCache(final String database, final String
tableName) {
+ super(database, tableName);
+ }
+
+ public boolean parseRawExpression(
+ final TsTable tableInstance,
+ final List<String> attributeColumns,
+ final MPPQueryContext context) {
+ if (Objects.isNull(rawExpression)) {
+ return true;
+ }
+ final List<DeviceEntry> entries = new ArrayList<>();
+ final boolean needFetch =
+ super.parseRawExpression(entries, tableInstance, attributeColumns,
context);
+ if (!needFetch) {
+ results =
+ entries.stream()
+ .map(
+ deviceEntry ->
+ ShowDevicesResult.convertDeviceEntry2ShowDeviceResult(
+ deviceEntry, attributeColumns))
+ .collect(Collectors.toList());
+ }
+ return needFetch;
+ }
+
+ public List<ColumnHeader> getColumnHeaderList() {
+ return columnHeaderList;
+ }
+
+ public void setColumnHeaderList() {
+ this.columnHeaderList = getDeviceColumnHeaderList(database, tableName);
+ }
+
+ public static List<ColumnHeader> getDeviceColumnHeaderList(
+ final String database, final String tableName) {
+ return DataNodeTableCache.getInstance().getTable(database,
tableName).getColumnList().stream()
+ .filter(
+ columnSchema ->
+
columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)
+ ||
columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE))
+ .map(
+ columnSchema ->
+ new ColumnHeader(columnSchema.getColumnName(),
columnSchema.getDataType()))
+ .collect(Collectors.toList());
+ }
+
+ public abstract DatasetHeader getDataSetHeader();
+
+ public abstract TsBlock getTsBlock();
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDevice.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
similarity index 66%
rename from
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDevice.java
rename to
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
index eeef4e8b6e8..dd0d77194a9 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDevice.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
@@ -20,9 +20,14 @@
package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
import org.apache.iotdb.db.queryengine.common.SessionInfo;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.MetadataUtil;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
+import
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.TableDeviceSchemaFetcher;
+import
org.apache.iotdb.db.queryengine.plan.relational.planner.ir.ExtractCommonPredicatesExpressionRewriter;
import org.apache.tsfile.file.metadata.IDeviceID;
@@ -31,17 +36,16 @@ import java.util.List;
import java.util.Objects;
// TODO table metadata: reuse query distinct logic
-public abstract class AbstractQueryDevice extends Statement {
+public abstract class AbstractTraverseDevice extends Statement {
- private String database;
+ protected String database;
- private String tableName;
+ protected String tableName;
// Temporary
private QualifiedName name;
- // Currently unused, shall be parsed into idDeterminedPredicateList and
idFuzzyPredicate on demand
- private Expression rawExpression;
+ protected Expression rawExpression;
/**
* The outer list represents the OR relation between different expression
lists.
@@ -59,25 +63,16 @@ public abstract class AbstractQueryDevice extends Statement
{
private List<IDeviceID> partitionKeyList;
// For sql-input show device usage
- protected AbstractQueryDevice(final QualifiedName name, final Expression
rawExpression) {
+ protected AbstractTraverseDevice(final QualifiedName name, final Expression
rawExpression) {
super(null);
this.name = name;
this.rawExpression = rawExpression;
}
- // For device fetch serving data query
- protected AbstractQueryDevice(
- final String database,
- final String tableName,
- final List<List<SchemaFilter>> idDeterminedFilterList,
- final Expression idFuzzyFilterList,
- final List<IDeviceID> partitionKeyList) {
+ protected AbstractTraverseDevice(final String database, final String
tableName) {
super(null);
this.database = database;
this.tableName = tableName;
- this.idDeterminedFilterList = idDeterminedFilterList;
- this.idFuzzyPredicate = idFuzzyFilterList;
- this.partitionKeyList = partitionKeyList;
}
public void parseQualifiedName(final SessionInfo sessionInfo) {
@@ -98,10 +93,44 @@ public abstract class AbstractQueryDevice extends Statement
{
return tableName;
}
+ public QualifiedName getName() {
+ return name;
+ }
+
public Expression getRawExpression() {
return rawExpression;
}
+ public void setRawExpression(final Expression rawExpression) {
+ this.rawExpression = rawExpression;
+ }
+
+ public boolean parseRawExpression(
+ final List<DeviceEntry> entries,
+ final TsTable tableInstance,
+ final List<String> attributeColumns,
+ final MPPQueryContext context) {
+ if (Objects.isNull(rawExpression)) {
+ return true;
+ }
+ rawExpression =
+
ExtractCommonPredicatesExpressionRewriter.extractCommonPredicates(rawExpression);
+ return TableDeviceSchemaFetcher.getInstance()
+ .parseFilter4TraverseDevice(
+ database,
+ tableInstance,
+ (rawExpression instanceof LogicalExpression
+ && ((LogicalExpression) rawExpression).getOperator()
+ == LogicalExpression.Operator.AND)
+ ? ((LogicalExpression) rawExpression).getTerms()
+ : Collections.singletonList(rawExpression),
+ this,
+ entries,
+ attributeColumns,
+ context,
+ true);
+ }
+
public List<List<SchemaFilter>> getIdDeterminedFilterList() {
if (idDeterminedFilterList == null) {
idDeterminedFilterList =
Collections.singletonList(Collections.emptyList());
@@ -109,10 +138,18 @@ public abstract class AbstractQueryDevice extends
Statement {
return idDeterminedFilterList;
}
+ public void setIdDeterminedFilterList(final List<List<SchemaFilter>>
idDeterminedFilterList) {
+ this.idDeterminedFilterList = idDeterminedFilterList;
+ }
+
public Expression getIdFuzzyPredicate() {
return idFuzzyPredicate;
}
+ public void setIdFuzzyPredicate(final Expression idFuzzyPredicate) {
+ this.idFuzzyPredicate = idFuzzyPredicate;
+ }
+
public boolean isIdDetermined() {
return Objects.nonNull(partitionKeyList);
}
@@ -121,6 +158,10 @@ public abstract class AbstractQueryDevice extends
Statement {
return partitionKeyList;
}
+ public void setPartitionKeyList(final List<IDeviceID> partitionKeyList) {
+ this.partitionKeyList = partitionKeyList;
+ }
+
@Override
public List<? extends Node> getChildren() {
return null;
@@ -130,7 +171,7 @@ public abstract class AbstractQueryDevice extends Statement
{
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- final AbstractQueryDevice that = (AbstractQueryDevice) o;
+ final AbstractTraverseDevice that = (AbstractTraverseDevice) o;
return Objects.equals(database, that.database)
&& Objects.equals(tableName, that.tableName)
&& Objects.equals(rawExpression, that.rawExpression)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDevice.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDevice.java
index d7813b131de..3b890d24896 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDevice.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDevice.java
@@ -19,13 +19,41 @@
package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
-public class CountDevice extends AbstractQueryDevice {
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+
+import java.util.Collections;
+
+public class CountDevice extends AbstractQueryDeviceWithCache {
+
+ public static final String COUNT_DEVICE_HEADER_STRING = "count(devices)";
// For sql-input show device usage
public CountDevice(final QualifiedName name, final Expression rawExpression)
{
super(name, rawExpression);
}
+ @Override
+ public DatasetHeader getDataSetHeader() {
+ return new DatasetHeader(
+ Collections.singletonList(new ColumnHeader(COUNT_DEVICE_HEADER_STRING,
TSDataType.INT64)),
+ true);
+ }
+
+ @Override
+ public TsBlock getTsBlock() {
+ final TsBlockBuilder tsBlockBuilder =
+ new TsBlockBuilder(Collections.singletonList(TSDataType.INT64));
+ tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
+ tsBlockBuilder.getColumnBuilder(0).writeLong(results.size());
+ tsBlockBuilder.declarePosition();
+ return tsBlockBuilder.build();
+ }
+
@Override
public <R, C> R accept(final AstVisitor<R, C> visitor, final C context) {
return visitor.visitCountDevice(this, context);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowDevice.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowDevice.java
index ca7cf135b86..cba444f6b51 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowDevice.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/ShowDevice.java
@@ -19,27 +19,42 @@
package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
-import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import
org.apache.iotdb.db.queryengine.execution.operator.schema.source.TableDeviceQuerySource;
-import org.apache.tsfile.file.metadata.IDeviceID;
+import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
-import java.util.List;
+import java.util.stream.Collectors;
-public class ShowDevice extends AbstractQueryDevice {
+public class ShowDevice extends AbstractQueryDeviceWithCache {
- // For sql-input show device usage
public ShowDevice(final QualifiedName name, final Expression rawExpression) {
super(name, rawExpression);
}
- // For device fetch serving data query
- public ShowDevice(
- final String database,
- final String tableName,
- final List<List<SchemaFilter>> idDeterminedPredicateList,
- final Expression idFuzzyFilterList,
- final List<IDeviceID> partitionKeyList) {
- super(database, tableName, idDeterminedPredicateList, idFuzzyFilterList,
partitionKeyList);
+ public ShowDevice(final String database, final String tableName) {
+ super(database, tableName);
+ }
+
+ @Override
+ public DatasetHeader getDataSetHeader() {
+ return new DatasetHeader(columnHeaderList, true);
+ }
+
+ @Override
+ public TsBlock getTsBlock() {
+ final TsBlockBuilder tsBlockBuilder =
+ new TsBlockBuilder(
+ columnHeaderList.stream()
+ .map(ColumnHeader::getColumnType)
+ .collect(Collectors.toList()));
+ results.forEach(
+ result ->
+ TableDeviceQuerySource.transformToTsBlockColumns(
+ result, tsBlockBuilder, database, tableName, columnHeaderList,
1));
+ return tsBlockBuilder.build();
}
@Override
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 391d5cd0ff2..7926c9226ea 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
@@ -535,20 +535,18 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
@Override
public Node visitShowDevicesStatement(final
RelationalSqlParser.ShowDevicesStatementContext ctx) {
- if (ctx.WHERE() != null || ctx.LIMIT() != null || ctx.OFFSET() != null) {
- throw new UnsupportedOperationException(
- "Show devices with WHERE/LIMIT/OFFSET is unsupported yet.");
+ if (ctx.LIMIT() != null || ctx.OFFSET() != null) {
+ throw new UnsupportedOperationException("Show devices with LIMIT/OFFSET
is unsupported yet.");
}
- return new ShowDevice(getQualifiedName(ctx.tableName), null);
+ return new ShowDevice(
+ getQualifiedName(ctx.tableName), visitIfPresent(ctx.where,
Expression.class).orElse(null));
}
@Override
public Node visitCountDevicesStatement(
final RelationalSqlParser.CountDevicesStatementContext ctx) {
- if (ctx.WHERE() != null) {
- throw new UnsupportedOperationException("Count devices with WHERE is
unsupported yet.");
- }
- return new CountDevice(getQualifiedName(ctx.tableName), null);
+ return new CountDevice(
+ getQualifiedName(ctx.tableName), visitIfPresent(ctx.where,
Expression.class).orElse(null));
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
index 2f0f805ea45..b24da4adb5a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
@@ -32,7 +32,6 @@ import
org.apache.iotdb.db.schemaengine.rescon.ISchemaRegionStatistics;
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowDevicesPlan;
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowNodesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowTimeSeriesPlan;
-import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl.ShowTableDevicesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.INodeSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
@@ -339,8 +338,8 @@ public interface ISchemaRegion {
ISchemaReader<INodeSchemaInfo> getNodeReader(IShowNodesPlan showNodesPlan)
throws MetadataException;
- ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
- final ShowTableDevicesPlan showTableDevicesPlan) throws
MetadataException;
+ ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(final PartialPath
pathPattern)
+ throws MetadataException;
ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
final String table, final List<Object[]> devicePathList) throws
MetadataException;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
index 22fbeaae2a7..14b21fcac6a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
@@ -62,7 +62,6 @@ import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.IMemMN
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowDevicesPlan;
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowNodesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowTimeSeriesPlan;
-import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl.ShowTableDevicesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.INodeSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
@@ -1402,12 +1401,10 @@ public class SchemaRegionMemoryImpl implements
ISchemaRegion {
}
@Override
- public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
- final ShowTableDevicesPlan showTableDevicesPlan) throws
MetadataException {
+ public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(final
PartialPath pathPattern)
+ throws MetadataException {
return mtree.getTableDeviceReader(
- showTableDevicesPlan.getDevicePattern(),
- showTableDevicesPlan.getDeviceFilter(),
- (pointer, name) -> deviceAttributeStore.getAttribute(pointer, name));
+ pathPattern, (pointer, name) ->
deviceAttributeStore.getAttribute(pointer, name));
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
index b790545b5d6..1baecf38a32 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
@@ -63,7 +63,6 @@ import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.pbtree.mnode.ICa
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowDevicesPlan;
import org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowNodesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.IShowTimeSeriesPlan;
-import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl.ShowTableDevicesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.INodeSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
@@ -1477,8 +1476,8 @@ public class SchemaRegionPBTreeImpl implements
ISchemaRegion {
}
@Override
- public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
- ShowTableDevicesPlan showTableDevicesPlan) throws MetadataException {
+ public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(final
PartialPath pathPattern)
+ throws MetadataException {
throw new UnsupportedOperationException();
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
index 04b8d9ac003..123002cb588 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
@@ -21,12 +21,10 @@ package
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.exception.MetadataException;
-import org.apache.iotdb.commons.path.ExtendedPartialPath;
import org.apache.iotdb.commons.path.MeasurementPath;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.path.PathPatternTree;
import org.apache.iotdb.commons.schema.SchemaConstant;
-import org.apache.iotdb.commons.schema.filter.SchemaFilter;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
import org.apache.iotdb.commons.schema.node.utils.IMNodeFactory;
@@ -1101,9 +1099,7 @@ public class MTreeBelowSGMemoryImpl {
// Used for device query/fetch with filters during show device or table query
public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
- final PartialPath pattern,
- final SchemaFilter deviceFilter,
- final BiFunction<Integer, String, String> attributeProvider)
+ final PartialPath pattern, final BiFunction<Integer, String, String>
attributeProvider)
throws MetadataException {
final EntityCollector<IDeviceSchemaInfo, IMemMNode> collector =
@@ -1127,9 +1123,6 @@ public class MTreeBelowSGMemoryImpl {
};
return new ISchemaReader<IDeviceSchemaInfo>() {
- private final DeviceFilterVisitor filterVisitor = new
DeviceFilterVisitor();
- private IDeviceSchemaInfo next;
-
public boolean isSuccess() {
return collector.isSuccess();
}
@@ -1147,33 +1140,15 @@ public class MTreeBelowSGMemoryImpl {
}
public boolean hasNext() {
- while (next == null && collector.hasNext()) {
- final IDeviceSchemaInfo temp = collector.next();
- if (deviceFilter == null || filterVisitor.process(deviceFilter,
temp)) {
- next = temp;
- }
- }
- return next != null;
+ return collector.hasNext();
}
public IDeviceSchemaInfo next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- final IDeviceSchemaInfo result = next;
- next = null;
- return result;
+ return collector.next();
}
};
}
- private int computeSmallestNullableIndex(final PartialPath partialPath) {
- if (!(partialPath instanceof ExtendedPartialPath)) {
- return partialPath.getNodeLength() - 1;
- }
- return 0;
- }
-
// used for device fetch with explicit device id/path during table insertion
public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
final String table,
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
index 767bc4c7935..28a5ea85fd7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
@@ -16,11 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
+
package org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.impl;
import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.UnaryOperator;
@@ -73,6 +78,19 @@ public class ShowDevicesResult extends ShowSchemaResult
implements IDeviceSchema
return rawNodes == null ? super.getPartialPath() : new
PartialPath(rawNodes);
}
+ public static ShowDevicesResult convertDeviceEntry2ShowDeviceResult(
+ final DeviceEntry entry, final List<String> attributeColumns) {
+ final ShowDevicesResult result =
+ new ShowDevicesResult(
+ entry.getDeviceID().toString(), null, -1, (String[])
entry.getDeviceID().getSegments());
+ final Map<String, String> attributeProviderMap = new HashMap<>();
+ for (int i = 0; i < attributeColumns.size(); ++i) {
+ attributeProviderMap.put(attributeColumns.get(i),
entry.getAttributeColumnValues().get(i));
+ }
+ result.setAttributeProvider(attributeProviderMap::get);
+ return result;
+ }
+
@Override
public String toString() {
return "ShowDevicesResult{"
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTableDeviceTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTableDeviceTest.java
index 82c5c953735..07b52d5b5c0 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTableDeviceTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTableDeviceTest.java
@@ -19,8 +19,6 @@
package org.apache.iotdb.db.metadata.schemaRegion;
-import org.apache.iotdb.commons.schema.filter.impl.multichildren.OrFilter;
-import org.apache.iotdb.commons.schema.filter.impl.singlechild.AttributeFilter;
import org.apache.iotdb.commons.schema.filter.impl.singlechild.IdFilter;
import org.apache.iotdb.commons.schema.filter.impl.singlechild.NotFilter;
import org.apache.iotdb.commons.schema.filter.impl.values.InFilter;
@@ -144,8 +142,7 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
3,
Arrays.asList(
new IdFilter(new PreciseFilter("hebei"), 0),
- new IdFilter(new PreciseFilter("p_1"), 1)),
- null);
+ new IdFilter(new PreciseFilter("p_1"), 1)));
Assert.assertEquals(2, deviceSchemaInfoList.size());
deviceSchemaInfoList =
@@ -153,8 +150,7 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
schemaRegion,
tableName,
3,
- Collections.singletonList(new IdFilter(new PreciseFilter("p_1"),
1)),
- null);
+ Collections.singletonList(new IdFilter(new PreciseFilter("p_1"),
1)));
Assert.assertEquals(3, deviceSchemaInfoList.size());
deviceSchemaInfoList =
@@ -162,31 +158,9 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
schemaRegion,
tableName,
3,
- Collections.singletonList(new IdFilter(new PreciseFilter("p_1"),
1)),
- new AttributeFilter(new PreciseFilter("daily"), "cycle"));
- Assert.assertEquals(1, deviceSchemaInfoList.size());
-
- deviceSchemaInfoList =
- SchemaRegionTestUtil.getTableDevice(
- schemaRegion,
- tableName,
- 3,
- Collections.emptyList(),
- new OrFilter(
- Arrays.asList(
- new IdFilter(new PreciseFilter("p_1"), 1),
- new AttributeFilter(new PreciseFilter("daily"),
"cycle"))));
- Assert.assertEquals(3, deviceSchemaInfoList.size());
-
- deviceSchemaInfoList =
- SchemaRegionTestUtil.getTableDevice(
- schemaRegion,
- tableName,
- 3,
- Collections.singletonList(new IdFilter(new
InFilter(Collections.singleton("d_1")), 2)),
- new AttributeFilter(new
LikeFilter(parseLikePatternToRegex("_____")), "cycle"));
+ Collections.singletonList(new IdFilter(new
InFilter(Collections.singleton("d_1")), 2)));
- Assert.assertEquals(1, deviceSchemaInfoList.size());
+ Assert.assertEquals(2, deviceSchemaInfoList.size());
// Test multi filters on one id
deviceSchemaInfoList =
@@ -196,8 +170,7 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
3,
Arrays.asList(
new IdFilter(new InFilter(new HashSet<>(Arrays.asList("d_0",
"d_1"))), 2),
- new IdFilter(new LikeFilter(parseLikePatternToRegex("__1")),
2)),
- null);
+ new IdFilter(new LikeFilter(parseLikePatternToRegex("__1")),
2)));
Assert.assertEquals(2, deviceSchemaInfoList.size());
}
@@ -247,8 +220,7 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
schemaRegion,
tableName,
3,
- Collections.singletonList(new IdFilter(new PreciseFilter((String)
null), 0)),
- null);
+ Collections.singletonList(new IdFilter(new PreciseFilter((String)
null), 0)));
Assert.assertEquals(1, deviceSchemaInfoList.size());
deviceSchemaInfoList =
@@ -256,30 +228,16 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
schemaRegion,
tableName,
3,
- Collections.singletonList(new IdFilter(new PreciseFilter((String)
null), 1)),
- null);
+ Collections.singletonList(new IdFilter(new PreciseFilter((String)
null), 1)));
Assert.assertEquals(2, deviceSchemaInfoList.size());
- deviceSchemaInfoList =
- SchemaRegionTestUtil.getTableDevice(
- schemaRegion,
- tableName,
- 3,
- Collections.emptyList(),
- new OrFilter(
- Arrays.asList(
- new IdFilter(new PreciseFilter((String) null), 2),
- new AttributeFilter(new PreciseFilter((String) null),
"cycle"))));
- Assert.assertEquals(4, deviceSchemaInfoList.size());
-
deviceSchemaInfoList =
SchemaRegionTestUtil.getTableDevice(
schemaRegion,
tableName,
3,
Collections.singletonList(
- new IdFilter(new NotFilter(new PreciseFilter((String) null)),
2)),
- null);
+ new IdFilter(new NotFilter(new PreciseFilter((String) null)),
2)));
Assert.assertEquals(2, deviceSchemaInfoList.size());
@@ -289,8 +247,7 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
tableName,
3,
Collections.singletonList(
- new IdFilter(new LikeFilter(parseLikePatternToRegex("%")), 2)),
- null);
+ new IdFilter(new LikeFilter(parseLikePatternToRegex("%")),
2)));
Assert.assertEquals(2, deviceSchemaInfoList.size());
}
@@ -336,19 +293,8 @@ public class SchemaRegionTableDeviceTest extends
AbstractSchemaRegionTest {
schemaRegion,
tableName,
4,
- Collections.singletonList(new IdFilter(new PreciseFilter("r_1"),
3)),
- null);
+ Collections.singletonList(new IdFilter(new PreciseFilter("r_1"),
3)));
Assert.assertEquals(1, deviceSchemaInfoList.size());
-
- // todo implement device query after table column extension
- // deviceSchemaInfoList =
- // SchemaRegionTestUtil.getTableDevice(
- // schemaRegion,
- // tableName,
- // 4,
- // Collections.singletonList(new DeviceIdFilter(3,
null)),
- // null);
- // Assert.assertEquals(2, deviceSchemaInfoList.size());
}
@Test
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTestUtil.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTestUtil.java
index d1480cf344e..d431073f070 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTestUtil.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTestUtil.java
@@ -28,7 +28,6 @@ import
org.apache.iotdb.commons.schema.filter.SchemaFilterFactory;
import org.apache.iotdb.commons.schema.filter.impl.DeviceFilterUtil;
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.SchemaRegionReadPlanFactory;
-import
org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl.ShowTableDevicesPlan;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.INodeSchemaInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
@@ -449,8 +448,7 @@ public class SchemaRegionTestUtil {
final ISchemaRegion schemaRegion,
final String table,
final int idColumnNum,
- final List<SchemaFilter> idDeterminedFilterList,
- final SchemaFilter idFuzzyFilter) {
+ final List<SchemaFilter> idDeterminedFilterList) {
final List<PartialPath> patternList =
DeviceFilterUtil.convertToDevicePattern(
schemaRegion.getDatabaseFullPath().substring(ROOT.length() + 1),
@@ -460,7 +458,7 @@ public class SchemaRegionTestUtil {
final List<IDeviceSchemaInfo> result = new ArrayList<>();
for (final PartialPath pattern : patternList) {
try (final ISchemaReader<IDeviceSchemaInfo> reader =
- schemaRegion.getTableDeviceReader(new ShowTableDevicesPlan(pattern,
idFuzzyFilter))) {
+ schemaRegion.getTableDeviceReader(pattern)) {
while (reader.hasNext()) {
result.add(reader.next());
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
index f7ca7932cfe..f4360e5f807 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
@@ -74,7 +74,7 @@ public class TsTable {
private transient int idNums = 0;
- public TsTable(String tableName) {
+ public TsTable(final String tableName) {
this.tableName = tableName;
columnSchemaMap.put(TIME_COLUMN_NAME, TIME_COLUMN_SCHEMA);
}
@@ -83,7 +83,7 @@ public class TsTable {
return tableName;
}
- public TsTableColumnSchema getColumnSchema(String columnName) {
+ public TsTableColumnSchema getColumnSchema(final String columnName) {
readWriteLock.readLock().lock();
try {
return columnSchemaMap.get(columnName);
@@ -92,7 +92,7 @@ public class TsTable {
}
}
- public void addColumnSchema(TsTableColumnSchema columnSchema) {
+ public void addColumnSchema(final TsTableColumnSchema columnSchema) {
readWriteLock.writeLock().lock();
try {
columnSchemaMap.put(columnSchema.getColumnName(), columnSchema);