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 772bab4abe0 Fix display of Blob type in last query
772bab4abe0 is described below

commit 772bab4abe078b1f843736df1c57369c18416c50
Author: Weihao Li <[email protected]>
AuthorDate: Wed Jul 16 06:41:26 2025 +0800

    Fix display of Blob type in last query
---
 .../db/it/last/IoTDBLastQueryLastCacheIT.java      |  2 +-
 .../plan/planner/LocalExecutionPlanContext.java    | 13 ++++++++-----
 .../plan/planner/LogicalPlanBuilder.java           |  6 +++++-
 .../plan/planner/OperatorTreeGenerator.java        | 19 +++++++++++--------
 .../plan/node/process/last/LastQueryNode.java      | 12 ++++++++++--
 .../plan/node/source/LastQueryScanNode.java        | 22 +++++++++++++++++++++-
 .../plan/planner/distribution/LastQueryTest.java   |  1 +
 .../logical/DataQueryLogicalPlannerTest.java       |  5 ++++-
 .../node/source/LastQueryScanNodeSerdeTest.java    |  2 ++
 9 files changed, 63 insertions(+), 19 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
index c4584f22fab..1c69857a3c5 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
@@ -183,7 +183,7 @@ public class IoTDBLastQueryLastCacheIT {
   }
 
   @Test
-  public void testLastQuerySortWithBlobType() {
+  public void testLastQueryWithBlobType() {
     String[] expectedHeader =
         new String[] {TIMESTAMP_STR, TIMESERIES_STR, VALUE_STR, DATA_TYPE_STR};
     String[] retArray =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanContext.java
index de4f99ff089..6c9d52dbe8c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanContext.java
@@ -83,8 +83,8 @@ public class LocalExecutionPlanContext {
   private List<TSDataType> cachedDataTypes;
 
   // left is cached last value in last query
-  // right is full path for each cached last value
-  private List<Pair<TimeValuePair, Binary>> cachedLastValueAndPathList;
+  // right is full path and DataType for each cached last value
+  private List<Pair<TimeValuePair, Pair<Binary, TSDataType>>> 
cachedLastValueAndPathList;
 
   // whether we need to update last cache
   private boolean needUpdateLastCache;
@@ -274,15 +274,18 @@ public class LocalExecutionPlanContext {
     this.needUpdateLastCache = needUpdateLastCache;
   }
 
-  public void addCachedLastValue(TimeValuePair timeValuePair, String fullPath) 
{
+  public void addCachedLastValue(
+      TimeValuePair timeValuePair, String fullPath, TSDataType dataType) {
     if (cachedLastValueAndPathList == null) {
       cachedLastValueAndPathList = new ArrayList<>();
     }
     cachedLastValueAndPathList.add(
-        new Pair<>(timeValuePair, new Binary(fullPath, 
TSFileConfig.STRING_CHARSET)));
+        new Pair<>(
+            timeValuePair,
+            new Pair<>(new Binary(fullPath, TSFileConfig.STRING_CHARSET), 
dataType)));
   }
 
-  public List<Pair<TimeValuePair, Binary>> getCachedLastValueAndPathList() {
+  public List<Pair<TimeValuePair, Pair<Binary, TSDataType>>> 
getCachedLastValueAndPathList() {
     return cachedLastValueAndPathList;
   }
 
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 84d0d84224d..9dbb0b8274d 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
@@ -257,6 +257,8 @@ public class LogicalPlanBuilder {
               sourceExpression.isViewExpression()
                   ? sourceExpression.getViewPath().getFullPath()
                   : null;
+          TSDataType outputViewPathType =
+              outputViewPath == null ? null : selectedPath.getSeriesType();
 
           PartialPath devicePath = selectedPath.getDevicePath();
           // For expression with view path, we do not use the deviceId in 
Map.Entry because it is a
@@ -268,7 +270,8 @@ public class LogicalPlanBuilder {
                   devicePath,
                   selectedPath.isUnderAlignedEntity(),
                   
Collections.singletonList(selectedPath.getMeasurementSchema()),
-                  outputViewPath);
+                  outputViewPath,
+                  outputViewPathType);
           this.context.reserveMemoryForFrontEnd(memCost);
         }
       } else {
@@ -291,6 +294,7 @@ public class LogicalPlanBuilder {
                 devicePath,
                 aligned,
                 measurementSchemas,
+                null,
                 null);
         this.context.reserveMemoryForFrontEnd(memCost);
       }
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 505af22ffc7..55b2defa543 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
@@ -3047,9 +3047,11 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
         }
       } else { //  cached last value is satisfied, put it into 
LastCacheScanOperator
         if (node.getOutputViewPath() != null) {
-          context.addCachedLastValue(timeValuePair, node.getOutputViewPath());
+          context.addCachedLastValue(
+              timeValuePair, node.getOutputViewPath(), 
node.getOutputViewPathType());
         } else {
-          context.addCachedLastValue(timeValuePair, 
measurementPath.getFullPath());
+          context.addCachedLastValue(
+              timeValuePair, measurementPath.getFullPath(), 
measurementSchema.getType());
         }
       }
     }
@@ -3097,7 +3099,7 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
             .filter(Objects::nonNull)
             .collect(Collectors.toList());
 
-    List<Pair<TimeValuePair, Binary>> cachedLastValueAndPathList =
+    List<Pair<TimeValuePair, Pair<Binary, TSDataType>>> 
cachedLastValueAndPathList =
         context.getCachedLastValueAndPathList();
 
     int initSize = cachedLastValueAndPathList != null ? 
cachedLastValueAndPathList.size() : 0;
@@ -3109,9 +3111,9 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
         LastQueryUtil.appendLastValueRespectBlob(
             builder,
             timeValuePair.getTimestamp(),
-            cachedLastValueAndPathList.get(i).right,
+            cachedLastValueAndPathList.get(i).right.getLeft(),
             timeValuePair.getValue(),
-            timeValuePair.getValue().getDataType().name());
+            cachedLastValueAndPathList.get(i).right.getRight().name());
       }
       OperatorContext operatorContext =
           context
@@ -3127,7 +3129,8 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
           node.getTimeseriesOrdering() == ASC ? ASC_BINARY_COMPARATOR : 
DESC_BINARY_COMPARATOR;
       // sort values from last cache
       if (initSize > 0) {
-        cachedLastValueAndPathList.sort(Comparator.comparing(Pair::getRight, 
comparator));
+        cachedLastValueAndPathList.sort(
+            Comparator.comparing(pair -> pair.getRight().getLeft(), 
comparator));
       }
 
       TsBlockBuilder builder = LastQueryUtil.createTsBlockBuilder(initSize);
@@ -3136,9 +3139,9 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
         LastQueryUtil.appendLastValueRespectBlob(
             builder,
             timeValuePair.getTimestamp(),
-            cachedLastValueAndPathList.get(i).right,
+            cachedLastValueAndPathList.get(i).right.getLeft(),
             timeValuePair.getValue(),
-            timeValuePair.getValue().getDataType().name());
+            cachedLastValueAndPathList.get(i).right.getRight().name());
       }
 
       OperatorContext operatorContext =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
index 4ce3f29750c..cbae6e9abd9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
@@ -29,6 +29,7 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.LastQuerySc
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.SourceNode;
 import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
 
+import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.utils.RamUsageEstimator;
 import org.apache.tsfile.utils.ReadWriteIOUtils;
 import org.apache.tsfile.write.schema.IMeasurementSchema;
@@ -89,7 +90,8 @@ public class LastQueryNode extends MultiChildProcessNode {
       PartialPath devicePath,
       boolean aligned,
       List<IMeasurementSchema> measurementSchemas,
-      String outputViewPath) {
+      String outputViewPath,
+      TSDataType outputViewPathType) {
     List<Integer> idxList = new ArrayList<>(measurementSchemas.size());
     for (IMeasurementSchema measurementSchema : measurementSchemas) {
       int idx =
@@ -103,7 +105,13 @@ public class LastQueryNode extends MultiChildProcessNode {
     }
     LastQueryScanNode scanNode =
         new LastQueryScanNode(
-            id, devicePath, aligned, idxList, outputViewPath, 
globalMeasurementSchemaList);
+            id,
+            devicePath,
+            aligned,
+            idxList,
+            outputViewPath,
+            outputViewPathType,
+            globalMeasurementSchemaList);
     children.add(scanNode);
     return scanNode.ramBytesUsed();
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/LastQueryScanNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/LastQueryScanNode.java
index 30b10f51014..1d40c1457a2 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/LastQueryScanNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/LastQueryScanNode.java
@@ -31,6 +31,7 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeUtil;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
 
 import com.google.common.collect.ImmutableList;
+import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.utils.RamUsageEstimator;
 import org.apache.tsfile.utils.ReadWriteIOUtils;
 import org.apache.tsfile.write.schema.IMeasurementSchema;
@@ -64,6 +65,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode {
   private List<IMeasurementSchema> globalMeasurementSchemaList;
 
   private final String outputViewPath;
+  private final TSDataType outputViewPathType;
 
   // The id of DataRegion where the node will run
   private TRegionReplicaSet regionReplicaSet;
@@ -75,12 +77,14 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
       boolean aligned,
       List<Integer> indexOfMeasurementSchemas,
       String outputViewPath,
+      TSDataType outputViewPathType,
       List<IMeasurementSchema> globalMeasurementSchemaList) {
     super(id, new AtomicInteger(1));
     this.aligned = aligned;
     this.devicePath = devicePath;
     this.indexOfMeasurementSchemas = indexOfMeasurementSchemas;
     this.outputViewPath = outputViewPath;
+    this.outputViewPathType = outputViewPathType;
     this.globalMeasurementSchemaList = globalMeasurementSchemaList;
   }
 
@@ -90,7 +94,8 @@ public class LastQueryScanNode extends LastSeriesSourceNode {
       boolean aligned,
       List<Integer> indexOfMeasurementSchemas,
       AtomicInteger dataNodeSeriesScanNum,
-      String outputViewPath) {
+      String outputViewPath,
+      TSDataType outputViewPathType) {
     this(
         id,
         devicePath,
@@ -98,6 +103,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode {
         indexOfMeasurementSchemas,
         dataNodeSeriesScanNum,
         outputViewPath,
+        outputViewPathType,
         null);
   }
 
@@ -108,12 +114,14 @@ public class LastQueryScanNode extends 
LastSeriesSourceNode {
       List<Integer> indexOfMeasurementSchemas,
       AtomicInteger dataNodeSeriesScanNum,
       String outputViewPath,
+      TSDataType outputViewPathType,
       List<IMeasurementSchema> globalMeasurementSchemaList) {
     super(id, dataNodeSeriesScanNum);
     this.aligned = aligned;
     this.devicePath = devicePath;
     this.indexOfMeasurementSchemas = indexOfMeasurementSchemas;
     this.outputViewPath = outputViewPath;
+    this.outputViewPathType = outputViewPathType;
     this.globalMeasurementSchemaList = globalMeasurementSchemaList;
   }
 
@@ -124,6 +132,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
       List<Integer> indexOfMeasurementSchemas,
       AtomicInteger dataNodeSeriesScanNum,
       String outputViewPath,
+      TSDataType outputViewPathType,
       TRegionReplicaSet regionReplicaSet,
       boolean deviceInMultiRegion,
       List<IMeasurementSchema> globalMeasurementSchemaList) {
@@ -132,6 +141,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
     this.aligned = aligned;
     this.indexOfMeasurementSchemas = indexOfMeasurementSchemas;
     this.outputViewPath = outputViewPath;
+    this.outputViewPathType = outputViewPathType;
     this.regionReplicaSet = regionReplicaSet;
     this.deviceInMultiRegion = deviceInMultiRegion;
     this.globalMeasurementSchemaList = globalMeasurementSchemaList;
@@ -162,6 +172,10 @@ public class LastQueryScanNode extends 
LastSeriesSourceNode {
     return outputViewPath;
   }
 
+  public TSDataType getOutputViewPathType() {
+    return outputViewPathType;
+  }
+
   public String getOutputSymbolForSort() {
     if (outputViewPath != null) {
       return outputViewPath;
@@ -196,6 +210,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
         indexOfMeasurementSchemas,
         getDataNodeSeriesScanNum(),
         outputViewPath,
+        outputViewPathType,
         regionReplicaSet,
         deviceInMultiRegion,
         globalMeasurementSchemaList);
@@ -226,6 +241,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
         && Objects.equals(aligned, that.aligned)
         && Objects.equals(indexOfMeasurementSchemas, 
that.indexOfMeasurementSchemas)
         && Objects.equals(outputViewPath, that.outputViewPath)
+        && Objects.equals(outputViewPathType, that.outputViewPathType)
         && Objects.equals(regionReplicaSet, that.regionReplicaSet);
   }
 
@@ -275,6 +291,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
     ReadWriteIOUtils.write(outputViewPath == null, byteBuffer);
     if (outputViewPath != null) {
       ReadWriteIOUtils.write(outputViewPath, byteBuffer);
+      ReadWriteIOUtils.write(outputViewPathType, byteBuffer);
     }
     ReadWriteIOUtils.write(deviceInMultiRegion, byteBuffer);
   }
@@ -292,6 +309,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
     ReadWriteIOUtils.write(outputViewPath == null, stream);
     if (outputViewPath != null) {
       ReadWriteIOUtils.write(outputViewPath, stream);
+      ReadWriteIOUtils.write(outputViewPathType, stream);
     }
     ReadWriteIOUtils.write(deviceInMultiRegion, stream);
   }
@@ -308,6 +326,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
     int dataNodeSeriesScanNum = ReadWriteIOUtils.readInt(byteBuffer);
     boolean isNull = ReadWriteIOUtils.readBool(byteBuffer);
     String outputPathSymbol = isNull ? null : 
ReadWriteIOUtils.readString(byteBuffer);
+    TSDataType dataType = isNull ? null : 
ReadWriteIOUtils.readDataType(byteBuffer);
     boolean deviceInMultiRegion = ReadWriteIOUtils.readBool(byteBuffer);
     PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer);
     return new LastQueryScanNode(
@@ -317,6 +336,7 @@ public class LastQueryScanNode extends LastSeriesSourceNode 
{
         measurementSchemas,
         new AtomicInteger(dataNodeSeriesScanNum),
         outputPathSymbol,
+        dataType,
         null,
         deviceInMultiRegion,
         null);
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/LastQueryTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/LastQueryTest.java
index e1893916d9e..86eb189680f 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/LastQueryTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/LastQueryTest.java
@@ -198,6 +198,7 @@ public class LastQueryTest {
           selectPath.getDevicePath(),
           selectPath.isUnderAlignedEntity(),
           Collections.singletonList(selectPath.getMeasurementSchema()),
+          null,
           null);
     }
 
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
index b92ef232d3d..2298b6ab631 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
@@ -89,6 +89,7 @@ public class DataQueryLogicalPlannerTest {
         d1s1Path.getDevicePath(),
         d1s1Path.isUnderAlignedEntity(),
         measurementSchemas,
+        null,
         null);
 
     measurementSchemas =
@@ -102,11 +103,12 @@ public class DataQueryLogicalPlannerTest {
         d2s1Path.getDevicePath(),
         d2s1Path.isUnderAlignedEntity(),
         measurementSchemas,
+        null,
         null);
 
     AlignedPath aPath = (AlignedPath) schemaMap.get("root.sg.d2.a");
     lastQueryNode.addDeviceLastQueryScanNode(
-        queryId.genPlanNodeId(), aPath.getDevicePath(), true, 
aPath.getSchemaList(), null);
+        queryId.genPlanNodeId(), aPath.getDevicePath(), true, 
aPath.getSchemaList(), null, null);
 
     PlanNode actualPlan = parseSQLToPlanNode(sql);
     Assert.assertEquals(actualPlan, lastQueryNode);
@@ -132,6 +134,7 @@ public class DataQueryLogicalPlannerTest {
         s3Path.getDevicePath(),
         s3Path.isUnderAlignedEntity(),
         measurementSchemas,
+        null,
         null);
 
     SortNode sortNode =
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java
index 270411f3f51..68a7fa0df0d 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java
@@ -44,6 +44,7 @@ public class LastQueryScanNodeSerdeTest {
             true,
             Arrays.asList(0, 1),
             null,
+            null,
             Arrays.asList(
                 new MeasurementSchema("s1", TSDataType.INT32),
                 new MeasurementSchema("s0", TSDataType.BOOLEAN)));
@@ -59,6 +60,7 @@ public class LastQueryScanNodeSerdeTest {
             false,
             Arrays.asList(0, 1),
             null,
+            null,
             Arrays.asList(
                 new MeasurementSchema("s1", TSDataType.INT32),
                 new MeasurementSchema("s0", TSDataType.BOOLEAN)));

Reply via email to