This is an automated email from the ASF dual-hosted git repository. zyk pushed a commit to branch table-model-debug in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 34e5b0e5ac3a7a69906d50f7a6f9e4e62ea69d34 Author: MarcosZyk <[email protected]> AuthorDate: Sun Apr 21 21:18:23 2024 +0800 implement schema filter --- .../iotdb/confignode/conf/ConfigNodeConfig.java | 2 +- .../schema/source/SchemaSourceFactory.java | 11 + .../schema/source/TableDeviceSchemaSource.java | 226 +++++++++++++++++++++ .../queryengine/plan/analyze/AnalyzeVisitor.java | 70 +++++++ .../plan/planner/LogicalPlanBuilder.java | 20 ++ .../plan/planner/LogicalPlanVisitor.java | 40 ++++ .../plan/planner/OperatorTreeGenerator.java | 22 ++ .../planner/distribution/ExchangeNodeAdder.java | 6 + .../plan/planner/plan/node/PlanVisitor.java | 5 + .../node/metedata/read/TableDeviceScanNode.java | 141 +++++++++++++ .../analyzer/schema/TableModelSchemaFetcher.java | 212 ++++++++++++++++++- .../plan/relational/metadata/DeviceEntry.java | 10 + .../relational/metadata/TableMetadataImpl.java | 18 +- .../planner/optimizations/IndexScan.java | 3 + .../plan/statement/StatementVisitor.java | 5 + .../metadata/ShowTableDevicesStatement.java | 69 +++++++ .../schemaengine/schemaregion/ISchemaRegion.java | 3 + .../attribute/DeviceAttributeStore.java | 7 +- .../attribute/IDeviceAttributeStore.java | 2 + .../schemaregion/impl/SchemaRegionMemoryImpl.java | 13 +- .../schemaregion/impl/SchemaRegionPBTreeImpl.java | 7 + .../mtree/impl/mem/MTreeBelowSGMemoryImpl.java | 82 +++++++- .../read/req/impl/ShowTableDevicesPlan.java | 40 ++++ .../read/resp/info/IDeviceSchemaInfo.java | 2 + .../read/resp/info/impl/ShowDevicesResult.java | 12 ++ .../utils/filter/DeviceFilterVisitor.java | 12 ++ .../commons/schema/filter/SchemaFilterType.java | 11 + .../commons/schema/filter/SchemaFilterVisitor.java | 15 ++ .../schema/filter/impl/DeviceAttributeFilter.java | 63 ++++++ .../commons/schema/filter/impl/DeviceIdFilter.java | 63 ++++++ .../iotdb/commons/schema/filter/impl/OrFilter.java | 74 +++++++ .../iotdb/db/relational/sql/parser/AstBuilder.java | 4 +- .../iotdb/db/relational/sql/tree/ShowDevice.java | 67 ++++++ 33 files changed, 1317 insertions(+), 20 deletions(-) diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeConfig.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeConfig.java index 3875bf09080..3177bf0c0fd 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeConfig.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeConfig.java @@ -101,7 +101,7 @@ public class ConfigNodeConfig { * DataRegionGroups for each Database. When set data_region_group_extension_policy=AUTO, this * parameter is the default minimal number of DataRegionGroups for each Database. */ - private int defaultDataRegionGroupNumPerDatabase = 2; + private int defaultDataRegionGroupNumPerDatabase = 1; /** The maximum number of DataRegions expected to be managed by each DataNode. */ private double dataRegionPerDataNode = 5.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 7fe10842579..9e3028b62f0 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 @@ -22,6 +22,7 @@ package org.apache.iotdb.db.queryengine.execution.operator.schema.source; 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.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; @@ -98,4 +99,14 @@ public class SchemaSourceFactory { PathPatternTree scope) { return new LogicalViewSchemaSource(pathPattern, limit, offset, schemaFilter, scope); } + + public static ISchemaSource<IDeviceSchemaInfo> getTableDeviceSchemaSource( + String database, + String tableName, + List<SchemaFilter> idDeterminedFilterList, + List<SchemaFilter> idFuzzyFilterList, + List<ColumnHeader> columnHeaderList) { + return new TableDeviceSchemaSource( + database, tableName, idDeterminedFilterList, idFuzzyFilterList, columnHeaderList); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceSchemaSource.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceSchemaSource.java new file mode 100644 index 00000000000..52999761142 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TableDeviceSchemaSource.java @@ -0,0 +1,226 @@ +package org.apache.iotdb.db.queryengine.execution.operator.schema.source; + +import org.apache.iotdb.commons.exception.runtime.SchemaExecutionException; +import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.impl.DeviceIdFilter; +import org.apache.iotdb.commons.schema.filter.impl.OrFilter; +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.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.read.common.block.TsBlockBuilder; +import org.apache.tsfile.utils.Binary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT; + +public class TableDeviceSchemaSource implements ISchemaSource<IDeviceSchemaInfo> { + + private String database; + + private String tableName; + + private List<SchemaFilter> idDeterminedFilterList; + + private List<SchemaFilter> idFuzzyFilterList; + + private List<ColumnHeader> columnHeaderList; + + public TableDeviceSchemaSource( + String database, + String tableName, + List<SchemaFilter> idDeterminedFilterList, + List<SchemaFilter> idFuzzyFilterList, + List<ColumnHeader> columnHeaderList) { + this.database = database; + this.tableName = tableName; + this.idDeterminedFilterList = idDeterminedFilterList; + this.idFuzzyFilterList = idFuzzyFilterList; + this.columnHeaderList = columnHeaderList; + } + + @Override + public ISchemaReader<IDeviceSchemaInfo> getSchemaReader(ISchemaRegion schemaRegion) { + List<PartialPath> devicePatternList = getDevicePatternList(); + return new ISchemaReader<IDeviceSchemaInfo>() { + + private ISchemaReader<IDeviceSchemaInfo> deviceReader; + private Throwable throwable; + private int index = 0; + + @Override + public boolean isSuccess() { + return throwable == null && (deviceReader == null || deviceReader.isSuccess()); + } + + @Override + public Throwable getFailure() { + if (throwable != null) { + return throwable; + } else if (deviceReader != null) { + return deviceReader.getFailure(); + } + return null; + } + + @Override + public ListenableFuture<?> isBlocked() { + return NOT_BLOCKED; + } + + @Override + public boolean hasNext() { + try { + if (throwable != null) { + return false; + } + if (deviceReader != null) { + if (deviceReader.hasNext()) { + return true; + } else { + deviceReader.close(); + if (!deviceReader.isSuccess()) { + throwable = deviceReader.getFailure(); + return false; + } + } + } + + while (index < devicePatternList.size()) { + deviceReader = + schemaRegion.getTableDeviceReader( + new ShowTableDevicesPlan(devicePatternList.get(index), idFuzzyFilterList)); + index++; + if (deviceReader.hasNext()) { + return true; + } else { + deviceReader.close(); + } + } + return false; + } catch (Exception e) { + throw new SchemaExecutionException(e.getMessage(), e); + } + } + + @Override + public IDeviceSchemaInfo next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return deviceReader.next(); + } + + @Override + public void close() throws Exception { + if (deviceReader != null) { + deviceReader.close(); + } + } + }; + } + + private List<PartialPath> getDevicePatternList() { + int length = DataNodeTableCache.getInstance().getTable(database, tableName).getIdNums() + 3; + String[] nodes = new String[length]; + Arrays.fill(nodes, "*"); + nodes[0] = PATH_ROOT; + nodes[1] = database; + nodes[2] = tableName; + Map<Integer, List<String>> orValueMap = new HashMap<>(); + for (SchemaFilter schemaFilter : idDeterminedFilterList) { + if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID)) { + DeviceIdFilter deviceIdFilter = (DeviceIdFilter) schemaFilter; + nodes[deviceIdFilter.getIndex() + 3] = deviceIdFilter.getValue(); + } else if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.OR)) { + OrFilter orFilter = (OrFilter) schemaFilter; + if (orFilter.getLeft().getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID) + && orFilter.getRight().getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID)) { + DeviceIdFilter deviceIdFilter = (DeviceIdFilter) orFilter.getLeft(); + nodes[deviceIdFilter.getIndex() + 3] = deviceIdFilter.getValue(); + deviceIdFilter = (DeviceIdFilter) orFilter.getLeft(); + orValueMap + .computeIfAbsent(deviceIdFilter.getIndex(), k -> new ArrayList<>()) + .add(deviceIdFilter.getValue()); + } + } + } + + PartialPath path = new PartialPath(nodes); + List<PartialPath> pathList = new ArrayList<>(); + pathList.add(path); + for (Map.Entry<Integer, List<String>> entry : orValueMap.entrySet()) { + for (int i = 0, size = pathList.size(); i < size; i++) { + for (String value : entry.getValue()) { + nodes = Arrays.copyOf(pathList.get(i).getNodes(), length); + nodes[entry.getKey() + 3] = value; + path = new PartialPath(nodes); + pathList.add(path); + } + } + } + + return pathList; + } + + @Override + public List<ColumnHeader> getInfoQueryColumnHeaders() { + return columnHeaderList; + } + + @Override + public void transformToTsBlockColumns( + IDeviceSchemaInfo schemaInfo, TsBlockBuilder builder, String database) { + builder.getTimeColumnBuilder().writeLong(0L); + int resultIndex = 0; + int idIndex = 0; + PartialPath devicePath = schemaInfo.getPartialPath(); + TsTable table = DataNodeTableCache.getInstance().getTable(this.database, tableName); + TsTableColumnSchema columnSchema; + for (ColumnHeader columnHeader : columnHeaderList) { + columnSchema = table.getColumnSchema(columnHeader.getColumnName()); + if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)) { + builder + .getColumnBuilder(resultIndex) + .writeBinary( + new Binary(devicePath.getNodes()[idIndex + 3], TSFileConfig.STRING_CHARSET)); + idIndex++; + } else if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE)) { + builder + .getColumnBuilder(resultIndex) + .writeBinary( + new Binary( + schemaInfo.getAttributeValue(columnHeader.getColumnName()), + TSFileConfig.STRING_CHARSET)); + } + resultIndex++; + } + builder.declarePosition(); + } + + @Override + public boolean hasSchemaStatistic(ISchemaRegion schemaRegion) { + return false; + } + + @Override + public long getSchemaStatistic(ISchemaRegion schemaRegion) { + return 0; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java index f60893d2cd7..bd94bf2b0fd 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java @@ -33,6 +33,11 @@ import org.apache.iotdb.commons.partition.SchemaPartition; 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.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.impl.DeviceIdFilter; +import org.apache.iotdb.commons.schema.filter.impl.OrFilter; +import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema; import org.apache.iotdb.commons.schema.view.LogicalViewSchema; import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression; import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics; @@ -127,6 +132,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowCurrentTimest import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDatabaseStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDevicesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTTLStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTableDevicesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTimeSeriesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ActivateTemplateStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.BatchActivateTemplateStatement; @@ -180,6 +186,7 @@ import static org.apache.iotdb.commons.conf.IoTDBConstant.ALLOWED_SCHEMA_PROPS; import static org.apache.iotdb.commons.conf.IoTDBConstant.DEADBAND; import static org.apache.iotdb.commons.conf.IoTDBConstant.LOSS; import static org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD; +import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT; import static org.apache.iotdb.commons.schema.SchemaConstant.ALL_MATCH_PATTERN; import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.DEVICE; import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.ENDTIME; @@ -3700,4 +3707,67 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> return analysis; } + + @Override + public Analysis visitShowTableDevices( + ShowTableDevicesStatement statement, MPPQueryContext context) { + context.setQueryType(QueryType.READ); + Analysis analysis = new Analysis(); + analysis.setStatement(statement); + + String database = statement.getDatabase(); + String tableName = statement.getTableName(); + List<TsTableColumnSchema> columnSchemaList = + DataNodeTableCache.getInstance().getTable(database, tableName).getColumnList(); + + int length = DataNodeTableCache.getInstance().getTable(database, tableName).getIdNums() + 3 + 1; + String[] nodes = new String[length]; + Arrays.fill(nodes, "*"); + nodes[0] = PATH_ROOT; + nodes[1] = database; + nodes[2] = tableName; + nodes[nodes.length - 1] = ONE_LEVEL_PATH_WILDCARD; + Map<Integer, List<String>> orValueMap = new HashMap<>(); + for (SchemaFilter schemaFilter : statement.getIdDeterminedFilterList()) { + if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID)) { + DeviceIdFilter deviceIdFilter = (DeviceIdFilter) schemaFilter; + nodes[deviceIdFilter.getIndex() + 3] = deviceIdFilter.getValue(); + } else if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.OR)) { + OrFilter orFilter = (OrFilter) schemaFilter; + if (orFilter.getLeft().getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID) + && orFilter.getRight().getSchemaFilterType().equals(SchemaFilterType.DEVICE_ID)) { + DeviceIdFilter deviceIdFilter = (DeviceIdFilter) orFilter.getLeft(); + nodes[deviceIdFilter.getIndex() + 3] = deviceIdFilter.getValue(); + deviceIdFilter = (DeviceIdFilter) orFilter.getLeft(); + orValueMap + .computeIfAbsent(deviceIdFilter.getIndex(), k -> new ArrayList<>()) + .add(deviceIdFilter.getValue()); + } + } + } + PathPatternTree patternTree = new PathPatternTree(); + PartialPath path = new PartialPath(nodes); + patternTree.appendFullPath(path); + List<PartialPath> pathList = new ArrayList<>(); + pathList.add(path); + for (Map.Entry<Integer, List<String>> entry : orValueMap.entrySet()) { + for (int i = 0, size = pathList.size(); i < size; i++) { + for (String value : entry.getValue()) { + nodes = Arrays.copyOf(pathList.get(i).getNodes(), length); + nodes[entry.getKey() + 3] = value; + path = new PartialPath(nodes); + pathList.add(path); + patternTree.appendFullPath(path); + } + } + } + + SchemaPartition partition = + partitionFetcher.getOrCreateSchemaPartition( + patternTree, context.getSession().getUserName()); + + analysis.setSchemaPartitionInfo(partition); + + return analysis; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java index 2a56d0e8140..1d31828c51b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java @@ -30,6 +30,7 @@ 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.MPPQueryContext; +import org.apache.iotdb.db.queryengine.common.header.ColumnHeader; import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant; import org.apache.iotdb.db.queryengine.execution.aggregation.AccumulatorFactory; import org.apache.iotdb.db.queryengine.execution.operator.AggregationUtil; @@ -54,6 +55,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.Sche import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaFetchScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryMergeNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryOrderByHeatNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TableDeviceScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesCountNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesSchemaScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.AggregationNode; @@ -1642,4 +1644,22 @@ public class LogicalPlanBuilder { new SlidingTimeColumnGeneratorParameter(groupByTimeParameter, ascending)); return this; } + + public LogicalPlanBuilder planTableDeviceSource( + String database, + String tableName, + List<SchemaFilter> idDeterminedFilterList, + List<SchemaFilter> idFuzzyFilterList, + List<ColumnHeader> columnHeaderList) { + this.root = + new TableDeviceScanNode( + context.getQueryId().genPlanNodeId(), + database, + tableName, + idDeterminedFilterList, + idFuzzyFilterList, + columnHeaderList, + null); + return this; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java index ffd75a5b42c..d61ba35b164 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java @@ -21,10 +21,14 @@ package org.apache.iotdb.db.queryengine.plan.planner; import org.apache.iotdb.commons.path.AlignedPath; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory; +import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema; import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression; import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction; 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.ColumnHeaderConstant; +import org.apache.iotdb.db.queryengine.common.header.DatasetHeader; import org.apache.iotdb.db.queryengine.plan.analyze.Analysis; import org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer; import org.apache.iotdb.db.queryengine.plan.expression.Expression; @@ -84,6 +88,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateTimeSeriesS import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildNodesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildPathsStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDevicesStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTableDevicesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTimeSeriesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ActivateTemplateStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.BatchActivateTemplateStatement; @@ -93,6 +98,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.ShowLogicalV import org.apache.iotdb.db.queryengine.plan.statement.pipe.PipeEnrichedStatement; import org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainAnalyzeStatement; import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement; +import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache; import org.apache.iotdb.db.schemaengine.template.Template; import org.apache.commons.lang3.StringUtils; @@ -1022,4 +1028,38 @@ public class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryConte createTableDeviceStatement.getAttributeNameList(), createTableDeviceStatement.getAttributeValueList()); } + + @Override + public PlanNode visitShowTableDevices( + ShowTableDevicesStatement statement, MPPQueryContext context) { + LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(analysis, context); + + List<TsTableColumnSchema> columnSchemaList = + DataNodeTableCache.getInstance() + .getTable(statement.getDatabase(), statement.getTableName()) + .getColumnList(); + + List<ColumnHeader> columnHeaderList = new ArrayList<>(columnSchemaList.size()); + for (TsTableColumnSchema columnSchema : columnSchemaList) { + if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID) + || columnSchema.getColumnCategory().equals(TsTableColumnCategory.ATTRIBUTE)) { + columnHeaderList.add( + new ColumnHeader(columnSchema.getColumnName(), columnSchema.getDataType())); + } + } + + analysis.setRespDatasetHeader(new DatasetHeader(columnHeaderList, true)); + + planBuilder = + planBuilder + .planTableDeviceSource( + statement.getDatabase(), + statement.getTableName(), + statement.getIdDeterminedFilterList(), + statement.getIdFuzzyFilterList(), + columnHeaderList) + .planSchemaQueryMerge(false); + + return planBuilder.getRoot(); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java index 3b13ac78a9d..cc3326e2cf6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java @@ -173,6 +173,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.Sche import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryMergeNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryOrderByHeatNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryScanNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TableDeviceScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesCountNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesSchemaScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.AggregationMergeSortNode; @@ -3262,4 +3263,25 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP return new ExplainAnalyzeOperator( operatorContext, operator, node.getQueryId(), node.isVerbose(), node.getTimeout()); } + + @Override + public Operator visitTableDeviceScan( + TableDeviceScanNode node, LocalExecutionPlanContext context) { + OperatorContext operatorContext = + context + .getDriverContext() + .addOperatorContext( + context.getNextOperatorId(), + node.getPlanNodeId(), + SchemaQueryScanOperator.class.getSimpleName()); + return new SchemaQueryScanOperator<>( + node.getPlanNodeId(), + operatorContext, + SchemaSourceFactory.getTableDeviceSchemaSource( + node.getDatabase(), + node.getTableName(), + node.getIdDeterminedFilterList(), + node.getIdFuzzyFilterList(), + node.getColumnHeaderList())); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java index 3ae7a3f126f..0c19a738a5d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java @@ -33,6 +33,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.Sche import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryMergeNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryOrderByHeatNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryScanNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TableDeviceScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.AggregationMergeSortNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.AggregationNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.DeviceMergeNode; @@ -154,6 +155,11 @@ public class ExchangeNodeAdder extends PlanVisitor<PlanNode, NodeGroupContext> { return processNoChildSourceNode(node, context); } + @Override + public PlanNode visitTableDeviceScan(TableDeviceScanNode node, NodeGroupContext context) { + return processNoChildSourceNode(node, context); + } + @Override public PlanNode visitSchemaFetchScan(SchemaFetchScanNode node, NodeGroupContext context) { return processNoChildSourceNode(node, context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java index 1fa71fe9aa2..a417be3f9b7 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java @@ -31,6 +31,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.Sche import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryMergeNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryOrderByHeatNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.SchemaQueryScanNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TableDeviceScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesCountNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.TimeSeriesSchemaScanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.write.ActivateTemplateNode; @@ -558,4 +559,8 @@ public abstract class PlanVisitor<R, C> { public R visitCreateTableDevice(CreateTableDeviceNode node, C context) { return visitPlan(node, context); } + + public R visitTableDeviceScan(TableDeviceScanNode node, C context) { + return visitPlan(node, context); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metedata/read/TableDeviceScanNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metedata/read/TableDeviceScanNode.java new file mode 100644 index 00000000000..3605963c6bc --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metedata/read/TableDeviceScanNode.java @@ -0,0 +1,141 @@ +package org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read; + +import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet; +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.db.queryengine.common.header.ColumnHeader; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class TableDeviceScanNode extends SchemaQueryScanNode { + + private String database; + + private String tableName; + + private List<SchemaFilter> idDeterminedFilterList; + + private List<SchemaFilter> idFuzzyFilterList; + + private List<ColumnHeader> columnHeaderList; + + private TRegionReplicaSet schemaRegionReplicaSet; + + public TableDeviceScanNode(PlanNodeId id) { + super(id); + } + + public TableDeviceScanNode( + PlanNodeId id, + String database, + String tableName, + List<SchemaFilter> idDeterminedFilterList, + List<SchemaFilter> idFuzzyFilterList, + List<ColumnHeader> columnHeaderList, + TRegionReplicaSet regionReplicaSet) { + super(id); + this.database = database; + this.tableName = tableName; + this.idDeterminedFilterList = idDeterminedFilterList; + this.idFuzzyFilterList = idFuzzyFilterList; + this.columnHeaderList = columnHeaderList; + this.schemaRegionReplicaSet = regionReplicaSet; + } + + public String getDatabase() { + return database; + } + + public String getTableName() { + return tableName; + } + + public List<SchemaFilter> getIdDeterminedFilterList() { + return idDeterminedFilterList; + } + + public List<SchemaFilter> getIdFuzzyFilterList() { + return idFuzzyFilterList; + } + + public List<ColumnHeader> getColumnHeaderList() { + return columnHeaderList; + } + + @Override + public void open() throws Exception {} + + @Override + public void setRegionReplicaSet(TRegionReplicaSet regionReplicaSet) { + this.schemaRegionReplicaSet = regionReplicaSet; + } + + @Override + public void close() throws Exception {} + + @Override + public TRegionReplicaSet getRegionReplicaSet() { + return schemaRegionReplicaSet; + } + + @Override + public PlanNode clone() { + return new TableDeviceScanNode( + getPlanNodeId(), + database, + tableName, + idDeterminedFilterList, + idFuzzyFilterList, + columnHeaderList, + schemaRegionReplicaSet); + } + + @Override + public List<String> getOutputColumnNames() { + return columnHeaderList.stream().map(ColumnHeader::getColumnName).collect(Collectors.toList()); + } + + @Override + protected void serializeAttributes(ByteBuffer byteBuffer) {} + + @Override + protected void serializeAttributes(DataOutputStream stream) throws IOException {} + + @Override + public <R, C> R accept(PlanVisitor<R, C> visitor, C context) { + return visitor.visitTableDeviceScan(this, context); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof TableDeviceScanNode)) return false; + if (!super.equals(o)) return false; + TableDeviceScanNode that = (TableDeviceScanNode) o; + return Objects.equals(database, that.database) + && Objects.equals(tableName, that.tableName) + && Objects.equals(idDeterminedFilterList, that.idDeterminedFilterList) + && Objects.equals(idFuzzyFilterList, that.idFuzzyFilterList) + && Objects.equals(columnHeaderList, that.columnHeaderList) + && Objects.equals(schemaRegionReplicaSet, that.schemaRegionReplicaSet); + } + + @Override + public int hashCode() { + return Objects.hash( + super.hashCode(), + database, + tableName, + idDeterminedFilterList, + idFuzzyFilterList, + columnHeaderList, + schemaRegionReplicaSet); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/schema/TableModelSchemaFetcher.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/schema/TableModelSchemaFetcher.java index ca4c7fee853..231708e71b8 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/schema/TableModelSchemaFetcher.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/schema/TableModelSchemaFetcher.java @@ -20,10 +20,19 @@ package org.apache.iotdb.db.queryengine.plan.relational.analyzer.schema; import org.apache.iotdb.commons.exception.IoTDBException; +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.impl.DeviceAttributeFilter; +import org.apache.iotdb.commons.schema.filter.impl.DeviceIdFilter; +import org.apache.iotdb.commons.schema.filter.impl.OrFilter; +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.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.protocol.session.SessionManager; import org.apache.iotdb.db.queryengine.common.MPPQueryContext; +import org.apache.iotdb.db.queryengine.common.header.ColumnHeader; import org.apache.iotdb.db.queryengine.plan.Coordinator; import org.apache.iotdb.db.queryengine.plan.analyze.ClusterPartitionFetcher; import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; @@ -31,10 +40,31 @@ import org.apache.iotdb.db.queryengine.plan.analyze.schema.ClusterSchemaFetcher; import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult; import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry; import org.apache.iotdb.db.queryengine.plan.statement.internal.CreateTableDeviceStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTableDevicesStatement; +import org.apache.iotdb.db.relational.sql.tree.ComparisonExpression; import org.apache.iotdb.db.relational.sql.tree.Expression; +import org.apache.iotdb.db.relational.sql.tree.Identifier; +import org.apache.iotdb.db.relational.sql.tree.Literal; +import org.apache.iotdb.db.relational.sql.tree.LogicalExpression; +import org.apache.iotdb.db.relational.sql.tree.StringLiteral; +import org.apache.iotdb.db.relational.sql.tree.SymbolReference; +import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache; import org.apache.iotdb.rpc.TSStatusCode; +import org.apache.tsfile.block.column.Column; +import org.apache.tsfile.file.metadata.IDeviceID; +import org.apache.tsfile.file.metadata.StringArrayDeviceID; +import org.apache.tsfile.read.common.block.TsBlock; +import org.apache.tsfile.utils.Pair; + +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_SEPARATOR; public class TableModelSchemaFetcher { @@ -85,6 +115,186 @@ public class TableModelSchemaFetcher { String table, List<Expression> expressionList, List<String> attributeColumns) { - return null; + List<DeviceEntry> deviceEntryList = new ArrayList<>(); + + Coordinator coordinator = Coordinator.getInstance(); + long queryId = SessionManager.getInstance().requestQueryId(); + Throwable t = null; + + TsTable tableInstance = DataNodeTableCache.getInstance().getTable(database, table); + Pair<List<SchemaFilter>, List<SchemaFilter>> filters = + transformExpression(expressionList, tableInstance); + List<SchemaFilter> idFilters = filters.getLeft(); + List<SchemaFilter> attributeFilters = filters.getRight(); + ShowTableDevicesStatement statement = + new ShowTableDevicesStatement(database, table, idFilters, attributeFilters); + ExecutionResult executionResult = + Coordinator.getInstance() + .executeForTreeModel( + statement, + queryId, + SessionManager.getInstance() + .getSessionInfo(SessionManager.getInstance().getCurrSession()), + "", + ClusterPartitionFetcher.getInstance(), + ClusterSchemaFetcher.getInstance(), + config.getQueryTimeoutThreshold()); + if (executionResult.status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + throw new RuntimeException( + new IoTDBException( + executionResult.status.getMessage(), executionResult.status.getCode())); + } + + List<ColumnHeader> columnHeaderList = + coordinator.getQueryExecution(queryId).getDatasetHeader().getColumnHeaders(); + int idLength = DataNodeTableCache.getInstance().getTable(database, table).getIdNums(); + Map<String, String> attributeMap; + + try { + while (coordinator.getQueryExecution(queryId).hasNextResult()) { + Optional<TsBlock> tsBlock; + try { + tsBlock = coordinator.getQueryExecution(queryId).getBatchResult(); + } catch (IoTDBException e) { + t = e; + throw new RuntimeException("Fetch Table Device Schema failed. ", e); + } + if (!tsBlock.isPresent() || tsBlock.get().isEmpty()) { + break; + } + Column[] columns = tsBlock.get().getValueColumns(); + for (int i = 0; i < tsBlock.get().getPositionCount(); i++) { + String[] nodes = new String[idLength + 1]; + nodes[0] = database + PATH_SEPARATOR + table; + int idIndex = 0; + attributeMap = new HashMap<>(); + for (int j = 0; j < columnHeaderList.size(); j++) { + TsTableColumnSchema columnSchema = + tableInstance.getColumnSchema(columnHeaderList.get(j).getColumnName()); + if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)) { + nodes[idIndex + 1] = columns[j].getBinary(i).toString(); + idIndex++; + } else { + attributeMap.put(columnSchema.getColumnName(), columns[j].getBinary(i).toString()); + } + } + IDeviceID deviceID = new StringArrayDeviceID(nodes); + deviceEntryList.add( + new DeviceEntry( + deviceID, + attributeColumns.stream().map(attributeMap::get).collect(Collectors.toList()))); + } + } + } catch (Throwable throwable) { + t = throwable; + throw throwable; + } finally { + coordinator.cleanupQueryExecution(queryId, null, t); + } + System.out.println(deviceEntryList); + return deviceEntryList; + } + + private Pair<List<SchemaFilter>, List<SchemaFilter>> transformExpression( + List<Expression> expressionList, TsTable table) { + List<SchemaFilter> idDeterminedFilters = new ArrayList<>(); + List<SchemaFilter> idFuzzyFilters = new ArrayList<>(); + Map<String, Integer> indexMap = getIdColumnIndex(table); + for (Expression expression : expressionList) { + if (expression == null) { + continue; + } + if (expression instanceof LogicalExpression) { + LogicalExpression logicalExpression = (LogicalExpression) expression; + SchemaFilter schemaFilter = transformToSchemaFilter(logicalExpression, table, indexMap); + if (hasAttribute(schemaFilter)) { + idFuzzyFilters.add(schemaFilter); + } else { + idDeterminedFilters.add(schemaFilter); + } + } else { + SchemaFilter schemaFilter = + transformToSchemaFilter((ComparisonExpression) expression, table, indexMap); + if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.DEVICE_ATTRIBUTE)) { + idFuzzyFilters.add(schemaFilter); + } else { + idDeterminedFilters.add(schemaFilter); + } + } + } + return new Pair<>(idDeterminedFilters, idFuzzyFilters); + } + + private boolean hasAttribute(SchemaFilter schemaFilter) { + if (schemaFilter.getSchemaFilterType().equals(SchemaFilterType.OR)) { + return hasAttribute(((OrFilter) schemaFilter).getLeft()) + || hasAttribute(((OrFilter) schemaFilter).getRight()); + } + + return schemaFilter.getSchemaFilterType().equals(SchemaFilterType.DEVICE_ATTRIBUTE); + } + + private SchemaFilter transformToSchemaFilter( + LogicalExpression logicalExpression, TsTable table, Map<String, Integer> indexMap) { + SchemaFilter left; + SchemaFilter right; + if (logicalExpression.getTerms().get(0) instanceof LogicalExpression) { + left = + transformToSchemaFilter( + (LogicalExpression) (logicalExpression.getChildren().get(0)), table, indexMap); + } else { + left = + transformToSchemaFilter( + (ComparisonExpression) (logicalExpression.getChildren().get(0)), table, indexMap); + } + if (logicalExpression.getTerms().get(1) instanceof LogicalExpression) { + right = + transformToSchemaFilter( + (LogicalExpression) (logicalExpression.getChildren().get(1)), table, indexMap); + } else { + right = + transformToSchemaFilter( + (ComparisonExpression) (logicalExpression.getChildren().get(1)), table, indexMap); + } + return new OrFilter(left, right); + } + + private SchemaFilter transformToSchemaFilter( + ComparisonExpression comparisonExpression, TsTable table, Map<String, Integer> indexMap) { + String columnName; + String value; + if (comparisonExpression.getLeft() instanceof Literal) { + value = ((StringLiteral) (comparisonExpression.getLeft())).getValue(); + if (comparisonExpression.getRight() instanceof Identifier) { + columnName = ((Identifier) (comparisonExpression.getRight())).getValue(); + } else { + columnName = ((SymbolReference) (comparisonExpression.getRight())).getName(); + } + } else { + value = ((StringLiteral) (comparisonExpression.getRight())).getValue(); + if (comparisonExpression.getLeft() instanceof Identifier) { + columnName = ((Identifier) (comparisonExpression.getLeft())).getValue(); + } else { + columnName = ((SymbolReference) (comparisonExpression.getLeft())).getName(); + } + } + if (table.getColumnSchema(columnName).getColumnCategory().equals(TsTableColumnCategory.ID)) { + return new DeviceIdFilter(indexMap.get(columnName), value); + } else { + return new DeviceAttributeFilter(columnName, value); + } + } + + private Map<String, Integer> getIdColumnIndex(TsTable table) { + Map<String, Integer> map = new HashMap<>(); + List<TsTableColumnSchema> columnSchemaList = table.getColumnList(); + int idIndex = 0; + for (TsTableColumnSchema columnSchema : columnSchemaList) { + if (columnSchema.getColumnCategory().equals(TsTableColumnCategory.ID)) { + map.put(columnSchema.getColumnName(), idIndex); + idIndex++; + } + } + return map; } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/DeviceEntry.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/DeviceEntry.java index 81b34e32c8b..cac441ef1f1 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/DeviceEntry.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/DeviceEntry.java @@ -40,4 +40,14 @@ public class DeviceEntry { public List<String> getAttributeColumnValues() { return attributeColumnValues; } + + @Override + public String toString() { + return "DeviceEntry{" + + "deviceID=" + + deviceID + + ", attributeColumnValues=" + + attributeColumnValues + + '}'; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java index 09947ddcd76..ce0d72e104b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java @@ -25,6 +25,7 @@ import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction; import org.apache.iotdb.db.exception.metadata.table.TableNotExistsException; import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.plan.relational.analyzer.schema.TableModelSchemaFetcher; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; import org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager; @@ -35,13 +36,9 @@ import org.apache.iotdb.db.relational.sql.tree.Expression; import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache; import org.apache.iotdb.db.utils.constant.SqlConstant; -import org.apache.tsfile.file.metadata.IDeviceID; -import org.apache.tsfile.file.metadata.StringArrayDeviceID; import org.apache.tsfile.read.common.type.Type; import org.apache.tsfile.read.common.type.TypeFactory; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Optional; @@ -260,13 +257,12 @@ public class TableMetadataImpl implements Metadata { QualifiedObjectName tableName, List<Expression> expressionList, List<String> attributeColumns) { - // fixme, perfect the real metadata impl - List<DeviceEntry> result = new ArrayList<>(); - IDeviceID deviceID1 = new StringArrayDeviceID("db.table1", "beijing", "a_1"); - IDeviceID deviceID2 = new StringArrayDeviceID("db.table1", "beijing", "b_1"); - result.add(new DeviceEntry(deviceID1, Arrays.asList("old", "low"))); - result.add(new DeviceEntry(deviceID2, Arrays.asList("new", "high"))); - return result; + return TableModelSchemaFetcher.getInstance() + .fetchDeviceSchema( + tableName.getDatabaseName(), + tableName.getObjectName(), + expressionList, + attributeColumns); } public static boolean isTwoNumericType(List<? extends Type> argumentTypes) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java index 0307f9bb0fe..a13551d3164 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java @@ -83,6 +83,9 @@ public class IndexScan implements RelationalPlanOptimizer { @Override public PlanNode visitFilter(FilterNode node, RewriterContext context) { context.setPredicate(node.getPredicate()); + for (PlanNode child : node.getChildren()) { + child.accept(this, context); + } return node; } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java index acb722fc933..be7f36de3fb 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java @@ -71,6 +71,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDevicesStatem import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowFunctionsStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowRegionStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTTLStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTableDevicesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTimeSeriesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTriggersStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowVariablesStatement; @@ -611,4 +612,8 @@ public abstract class StatementVisitor<R, C> { CreateTableDeviceStatement createTableDeviceStatement, C context) { return visitStatement(createTableDeviceStatement, context); } + + public R visitShowTableDevices(ShowTableDevicesStatement statement, C context) { + return visitStatement(statement, context); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/ShowTableDevicesStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/ShowTableDevicesStatement.java new file mode 100644 index 00000000000..0cb634830cd --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/ShowTableDevicesStatement.java @@ -0,0 +1,69 @@ +/* + * 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.statement.metadata; + +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; + +import java.util.List; + +public class ShowTableDevicesStatement extends ShowStatement { + + private final String database; + + private final String tableName; + + private final List<SchemaFilter> idDeterminedFilterList; + + private final List<SchemaFilter> idFuzzyFilterList; + + public ShowTableDevicesStatement( + String database, + String tableName, + List<SchemaFilter> idDeterminedFilterList, + List<SchemaFilter> idFuzzyFilterList) { + super(); + this.database = database; + this.tableName = tableName; + this.idDeterminedFilterList = idDeterminedFilterList; + this.idFuzzyFilterList = idFuzzyFilterList; + } + + public String getDatabase() { + return database; + } + + public String getTableName() { + return tableName; + } + + public List<SchemaFilter> getIdDeterminedFilterList() { + return idDeterminedFilterList; + } + + public List<SchemaFilter> getIdFuzzyFilterList() { + return idFuzzyFilterList; + } + + @Override + public <R, C> R accept(StatementVisitor<R, C> visitor, C context) { + return visitor.visitShowTableDevices(this, context); + } +} 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 43120723863..a8f814d4a9c 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,6 +32,7 @@ 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; @@ -314,5 +315,7 @@ public interface ISchemaRegion { ISchemaReader<INodeSchemaInfo> getNodeReader(IShowNodesPlan showNodesPlan) throws MetadataException; + ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(ShowTableDevicesPlan showTableDevicesPlan) + throws MetadataException; // endregion } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/DeviceAttributeStore.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/DeviceAttributeStore.java index 048d6eb5285..6a65fe17f1a 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/DeviceAttributeStore.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/DeviceAttributeStore.java @@ -120,12 +120,17 @@ public class DeviceAttributeStore implements IDeviceAttributeStore { @Override public void alterAttribute(int pointer, List<String> nameList, List<String> valueList) { - Map<String, String> attributeMap = deviceAttributeList.get((int) pointer); + Map<String, String> attributeMap = deviceAttributeList.get(pointer); for (int i = 0; i < nameList.size(); i++) { attributeMap.put(nameList.get(i), valueList.get(i)); } } + @Override + public String getAttribute(int pointer, String name) { + return deviceAttributeList.get(pointer).get(name); + } + private void serialize(OutputStream outputStream) throws IOException { ReadWriteIOUtils.write(deviceAttributeList.size(), outputStream); for (Map<String, String> attributeMap : deviceAttributeList) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/IDeviceAttributeStore.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/IDeviceAttributeStore.java index c5395a93a67..79f44d20bd2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/IDeviceAttributeStore.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/attribute/IDeviceAttributeStore.java @@ -34,4 +34,6 @@ public interface IDeviceAttributeStore { int createAttribute(List<String> nameList, List<String> valueList); void alterAttribute(int pointer, List<String> nameList, List<String> valueList); + + String getAttribute(int pointer, String name); } 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 13913fbb2ec..3aae464def1 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,6 +62,7 @@ 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; @@ -1245,7 +1246,8 @@ public class SchemaRegionMemoryImpl implements ISchemaRegion { @Override public ISchemaReader<IDeviceSchemaInfo> getDeviceReader(IShowDevicesPlan showDevicesPlan) throws MetadataException { - return mtree.getDeviceReader(showDevicesPlan); + return mtree.getDeviceReader( + showDevicesPlan, (pointer, name) -> deviceAttributeStore.getAttribute(pointer, name)); } @Override @@ -1275,6 +1277,15 @@ public class SchemaRegionMemoryImpl implements ISchemaRegion { return mtree.getNodeReader(showNodesPlan); } + @Override + public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader( + ShowTableDevicesPlan showTableDevicesPlan) throws MetadataException { + return mtree.getDeviceReader( + showTableDevicesPlan.getDevicePattern(), + showTableDevicesPlan.getAttributeFilter(), + (pointer, name) -> deviceAttributeStore.getAttribute(pointer, name)); + } + // endregion private static class RecoverOperationResult { 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 f0095babf9a..6cd1fcd1f93 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,6 +63,7 @@ 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; @@ -1354,6 +1355,12 @@ public class SchemaRegionPBTreeImpl implements ISchemaRegion { throws MetadataException { return mtree.getNodeReader(showNodesPlan); } + + @Override + public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader( + ShowTableDevicesPlan showTableDevicesPlan) { + throw new UnsupportedOperationException(); + } // endregion private static class RecoverOperationResult { 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 3c453801c7d..d78b8325a37 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 @@ -25,6 +25,7 @@ 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; @@ -91,6 +92,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.IntConsumer; @@ -951,7 +953,8 @@ public class MTreeBelowSGMemoryImpl { // region Interfaces for schema reader @SuppressWarnings("java:S2095") - public ISchemaReader<IDeviceSchemaInfo> getDeviceReader(IShowDevicesPlan showDevicesPlan) + public ISchemaReader<IDeviceSchemaInfo> getDeviceReader( + IShowDevicesPlan showDevicesPlan, BiFunction<Integer, String, String> attributeProvider) throws MetadataException { EntityCollector<IDeviceSchemaInfo, IMemMNode> collector = new EntityCollector<IDeviceSchemaInfo, IMemMNode>( @@ -963,8 +966,15 @@ public class MTreeBelowSGMemoryImpl { protected IDeviceSchemaInfo collectEntity(IDeviceMNode<IMemMNode> node) { PartialPath device = getPartialPathFromRootToNode(node.getAsMNode()); - return new ShowDevicesResult( - device.getFullPath(), node.isAlignedNullable(), node.getSchemaTemplateId()); + ShowDevicesResult result = + new ShowDevicesResult( + device.getFullPath(), node.isAlignedNullable(), node.getSchemaTemplateId()); + result.setAttributeProvider( + k -> + attributeProvider.apply( + ((TableDeviceInfo<IMemMNode>) node.getDeviceInfo()).getAttributePointer(), + k)); + return result; } }; if (showDevicesPlan.usingSchemaTemplate()) { @@ -995,7 +1005,8 @@ public class MTreeBelowSGMemoryImpl { public boolean hasNext() { while (next == null && collector.hasNext()) { IDeviceSchemaInfo temp = collector.next(); - if (filterVisitor.process(showDevicesPlan.getSchemaFilter(), temp)) { + if (showDevicesPlan.getSchemaFilter() == null + || filterVisitor.process(showDevicesPlan.getSchemaFilter(), temp)) { next = temp; } } @@ -1019,6 +1030,69 @@ public class MTreeBelowSGMemoryImpl { } } + public ISchemaReader<IDeviceSchemaInfo> getDeviceReader( + PartialPath pattern, + SchemaFilter attributeFilter, + BiFunction<Integer, String, String> attributeProvider) + throws MetadataException { + EntityCollector<IDeviceSchemaInfo, IMemMNode> collector = + new EntityCollector<IDeviceSchemaInfo, IMemMNode>(rootNode, pattern, store, false, null) { + + protected IDeviceSchemaInfo collectEntity(IDeviceMNode<IMemMNode> node) { + PartialPath device = getPartialPathFromRootToNode(node.getAsMNode()); + ShowDevicesResult result = + new ShowDevicesResult( + device.getFullPath(), node.isAlignedNullable(), node.getSchemaTemplateId()); + result.setAttributeProvider( + k -> + attributeProvider.apply( + ((TableDeviceInfo<IMemMNode>) node.getDeviceInfo()).getAttributePointer(), + k)); + return result; + } + }; + return new ISchemaReader<IDeviceSchemaInfo>() { + + private final DeviceFilterVisitor filterVisitor = new DeviceFilterVisitor(); + private IDeviceSchemaInfo next; + + public boolean isSuccess() { + return collector.isSuccess(); + } + + public Throwable getFailure() { + return collector.getFailure(); + } + + public void close() { + collector.close(); + } + + public ListenableFuture<?> isBlocked() { + return NOT_BLOCKED; + } + + public boolean hasNext() { + while (next == null && collector.hasNext()) { + IDeviceSchemaInfo temp = collector.next(); + if (attributeFilter == null || filterVisitor.process(attributeFilter, temp)) { + next = temp; + } + } + return next != null; + } + + public IDeviceSchemaInfo next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + IDeviceSchemaInfo result = next; + next = null; + return result; + } + }; + } + public ISchemaReader<ITimeSeriesSchemaInfo> getTimeSeriesReader( IShowTimeSeriesPlan showTimeSeriesPlan, Function<Long, Pair<Map<String, String>, Map<String, String>>> tagAndAttributeProvider) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/req/impl/ShowTableDevicesPlan.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/req/impl/ShowTableDevicesPlan.java new file mode 100644 index 00000000000..d3af79e093d --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/req/impl/ShowTableDevicesPlan.java @@ -0,0 +1,40 @@ +package org.apache.iotdb.db.schemaengine.schemaregion.read.req.impl; + +import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.impl.AndFilter; + +import java.util.List; + +public class ShowTableDevicesPlan { + + private PartialPath devicePattern; + + private SchemaFilter attributeFilter; + + public ShowTableDevicesPlan(PartialPath devicePattern, List<SchemaFilter> attributeFilterList) { + this.devicePattern = devicePattern; + this.attributeFilter = getAttributeFilter(attributeFilterList); + } + + private SchemaFilter getAttributeFilter(List<SchemaFilter> filterList) { + if (filterList.isEmpty()) { + return null; + } + AndFilter andFilter; + SchemaFilter latestFilter = filterList.get(0); + for (int i = 1; i < filterList.size(); i++) { + andFilter = new AndFilter(latestFilter, filterList.get(i)); + latestFilter = andFilter; + } + return latestFilter; + } + + public PartialPath getDevicePattern() { + return devicePattern; + } + + public SchemaFilter getAttributeFilter() { + return attributeFilter; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java index 9a670f9b44b..634f7d65461 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java @@ -24,4 +24,6 @@ public interface IDeviceSchemaInfo extends ISchemaInfo { Boolean isAligned(); int getTemplateId(); + + String getAttributeValue(String attributeKey); } 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 19aa1971008..8f4c5b95a6b 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 @@ -21,11 +21,14 @@ package org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.impl; import org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo; import java.util.Objects; +import java.util.function.Function; public class ShowDevicesResult extends ShowSchemaResult implements IDeviceSchemaInfo { private Boolean isAligned; private int templateId; + private Function<String, String> attributeProvider; + public ShowDevicesResult(String name, Boolean isAligned, int templateId) { super(name); this.isAligned = isAligned; @@ -40,6 +43,15 @@ public class ShowDevicesResult extends ShowSchemaResult implements IDeviceSchema return templateId; } + public void setAttributeProvider(Function<String, String> attributeProvider) { + this.attributeProvider = attributeProvider; + } + + @Override + public String getAttributeValue(String attributeKey) { + return attributeProvider.apply(attributeKey); + } + @Override public String toString() { return "ShowDevicesResult{" diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java index e1723193abf..0555aecf5ea 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java @@ -21,6 +21,8 @@ package org.apache.iotdb.db.schemaengine.schemaregion.utils.filter; import org.apache.iotdb.commons.schema.filter.SchemaFilter; import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor; +import org.apache.iotdb.commons.schema.filter.impl.DeviceAttributeFilter; +import org.apache.iotdb.commons.schema.filter.impl.DeviceIdFilter; import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter; import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter; import org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo; @@ -59,4 +61,14 @@ public class DeviceFilterVisitor extends SchemaFilterVisitor<IDeviceSchemaInfo> return false; } } + + @Override + public boolean visitDeviceIdFilter(DeviceIdFilter filter, IDeviceSchemaInfo info) { + return info.getPartialPath().getNodes()[filter.getIndex() + 3].equals(filter.getValue()); + } + + @Override + public boolean visitDeviceAttributeFilter(DeviceAttributeFilter filter, IDeviceSchemaInfo info) { + return info.getAttributeValue(filter.getKey()).equals(filter.getValue()); + } } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java index 285130f778e..66e9f15e939 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java @@ -26,6 +26,11 @@ public enum SchemaFilterType { VIEW_TYPE((short) 4), AND((short) 5), TEMPLATE_FILTER((short) 6), + + DEVICE_ID((short) 7), + DEVICE_ATTRIBUTE((short) 8), + + OR((short) 9), ; private final short code; @@ -54,6 +59,12 @@ public enum SchemaFilterType { return AND; case 6: return TEMPLATE_FILTER; + case 7: + return DEVICE_ID; + case 8: + return DEVICE_ATTRIBUTE; + case 9: + return OR; default: throw new IllegalArgumentException("Invalid input: " + code); } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java index d6861baab68..f503da64b15 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java @@ -20,6 +20,9 @@ package org.apache.iotdb.commons.schema.filter; import org.apache.iotdb.commons.schema.filter.impl.AndFilter; import org.apache.iotdb.commons.schema.filter.impl.DataTypeFilter; +import org.apache.iotdb.commons.schema.filter.impl.DeviceAttributeFilter; +import org.apache.iotdb.commons.schema.filter.impl.DeviceIdFilter; +import org.apache.iotdb.commons.schema.filter.impl.OrFilter; import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter; import org.apache.iotdb.commons.schema.filter.impl.TagFilter; import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter; @@ -69,4 +72,16 @@ public abstract class SchemaFilterVisitor<C> { public boolean visitAndFilter(AndFilter andFilter, C context) { return andFilter.getLeft().accept(this, context) && andFilter.getRight().accept(this, context); } + + public boolean visitOrFilter(OrFilter orFilter, C context) { + return orFilter.getLeft().accept(this, context) || orFilter.getRight().accept(this, context); + } + + public boolean visitDeviceIdFilter(DeviceIdFilter filter, C context) { + return visitFilter(filter, context); + } + + public boolean visitDeviceAttributeFilter(DeviceAttributeFilter filter, C context) { + return visitDeviceAttributeFilter(filter, context); + } } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceAttributeFilter.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceAttributeFilter.java new file mode 100644 index 00000000000..09736bf5b19 --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceAttributeFilter.java @@ -0,0 +1,63 @@ +/* + * 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.commons.schema.filter.impl; + +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class DeviceAttributeFilter extends SchemaFilter { + + private final String key; + + private final String value; + + public DeviceAttributeFilter(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + @Override + public <C> boolean accept(SchemaFilterVisitor<C> visitor, C node) { + return visitor.visitDeviceAttributeFilter(this, node); + } + + @Override + public SchemaFilterType getSchemaFilterType() { + return SchemaFilterType.DEVICE_ATTRIBUTE; + } + + @Override + public void serialize(ByteBuffer byteBuffer) {} + + @Override + public void serialize(DataOutputStream stream) throws IOException {} +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceIdFilter.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceIdFilter.java new file mode 100644 index 00000000000..eda64d90a8d --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/DeviceIdFilter.java @@ -0,0 +1,63 @@ +/* + * 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.commons.schema.filter.impl; + +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class DeviceIdFilter extends SchemaFilter { + + private final int index; + + private final String value; + + public DeviceIdFilter(int index, String value) { + this.index = index; + this.value = value; + } + + public int getIndex() { + return index; + } + + public String getValue() { + return value; + } + + @Override + public <C> boolean accept(SchemaFilterVisitor<C> visitor, C node) { + return visitor.visitDeviceIdFilter(this, node); + } + + @Override + public SchemaFilterType getSchemaFilterType() { + return SchemaFilterType.DEVICE_ID; + } + + @Override + public void serialize(ByteBuffer byteBuffer) {} + + @Override + public void serialize(DataOutputStream stream) throws IOException {} +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/OrFilter.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/OrFilter.java new file mode 100644 index 00000000000..1f57622719d --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/OrFilter.java @@ -0,0 +1,74 @@ +/* + * 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.commons.schema.filter.impl; + +import org.apache.iotdb.commons.schema.filter.SchemaFilter; +import org.apache.iotdb.commons.schema.filter.SchemaFilterType; +import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class OrFilter extends SchemaFilter { + private final SchemaFilter left; + private final SchemaFilter right; + + public OrFilter(SchemaFilter left, SchemaFilter right) { + // left and right should not be null + this.left = left; + this.right = right; + } + + public OrFilter(ByteBuffer byteBuffer) { + this.left = SchemaFilter.deserialize(byteBuffer); + this.right = SchemaFilter.deserialize(byteBuffer); + } + + public SchemaFilter getLeft() { + return left; + } + + public SchemaFilter getRight() { + return right; + } + + @Override + public <C> boolean accept(SchemaFilterVisitor<C> visitor, C node) { + return visitor.visitOrFilter(this, node); + } + + @Override + public SchemaFilterType getSchemaFilterType() { + return SchemaFilterType.AND; + } + + @Override + public void serialize(ByteBuffer byteBuffer) { + left.serialize(byteBuffer); + right.serialize(byteBuffer); + } + + @Override + public void serialize(DataOutputStream stream) throws IOException { + left.serialize(stream); + right.serialize(stream); + } +} diff --git a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java index 7fbc148ffdb..760b364bbe8 100644 --- a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java +++ b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java @@ -101,6 +101,7 @@ import org.apache.iotdb.db.relational.sql.tree.Select; import org.apache.iotdb.db.relational.sql.tree.SelectItem; import org.apache.iotdb.db.relational.sql.tree.SetProperties; import org.apache.iotdb.db.relational.sql.tree.ShowDB; +import org.apache.iotdb.db.relational.sql.tree.ShowDevice; import org.apache.iotdb.db.relational.sql.tree.ShowIndex; import org.apache.iotdb.db.relational.sql.tree.ShowTables; import org.apache.iotdb.db.relational.sql.tree.SimpleCaseExpression; @@ -382,7 +383,8 @@ public class AstBuilder extends RelationalSqlBaseVisitor<Node> { @Override public Node visitShowDevicesStatement(RelationalSqlParser.ShowDevicesStatementContext ctx) { - return super.visitShowDevicesStatement(ctx); + // todo parse where clause + return new ShowDevice(getLocation(ctx)); } @Override diff --git a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ShowDevice.java b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ShowDevice.java new file mode 100644 index 00000000000..4427238fe9a --- /dev/null +++ b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ShowDevice.java @@ -0,0 +1,67 @@ +/* + * 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.relational.sql.tree; + +import com.google.common.collect.ImmutableList; + +import javax.annotation.Nullable; + +import java.util.List; +import java.util.Objects; + +public class ShowDevice extends Statement { + + private Expression whereClause; + + public ShowDevice(@Nullable NodeLocation location) { + super(location); + } + + public void setWhereClause(Expression whereClause) { + this.whereClause = whereClause; + } + + public Expression getWhereClause() { + return whereClause; + } + + @Override + public List<? extends Node> getChildren() { + return ImmutableList.of(); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ShowDevice)) return false; + ShowDevice that = (ShowDevice) o; + return Objects.equals(whereClause, that.whereClause); + } + + @Override + public String toString() { + return "ShowDevice{" + "whereClause=" + whereClause + '}'; + } +}
