From be14b0cf9b8de666d553f8e6eb01c3ae8f1032ed Mon Sep 17 00:00:00 2001 From: Muhammad-Ikhwan-Fathulloh Date: Sun, 7 Jun 2026 00:41:43 +0700 Subject: [PATCH] [IOTDB-FIX] Fix LimitNode Serialization and NPE risk in Relational Engine This PR addresses a logical bug in the LimitNode where the tiesResolvingScheme field was being ignored during serialization and deserialization. It also fixes a potential NPE in deserialize(). --- .../relational/planner/node/LimitNode.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/planner/node/LimitNode.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/planner/node/LimitNode.java index 1f8991a32971d..ce4bd7876815a 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/planner/node/LimitNode.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/planner/node/LimitNode.java @@ -40,7 +40,6 @@ public class LimitNode extends SingleChildProcessNode { private final long count; - // TODO(beyyes) useless variable? private final Optional tiesResolvingScheme; // private final boolean partial; @@ -85,18 +84,27 @@ public List getOutputColumnNames() { protected void serializeAttributes(ByteBuffer byteBuffer) { PlanNodeType.TABLE_LIMIT_NODE.serialize(byteBuffer); ReadWriteIOUtils.write(count, byteBuffer); + ReadWriteIOUtils.write(tiesResolvingScheme.isPresent(), byteBuffer); + tiesResolvingScheme.ifPresent(scheme -> scheme.serialize(byteBuffer)); } @Override protected void serializeAttributes(DataOutputStream stream) throws IOException { PlanNodeType.TABLE_LIMIT_NODE.serialize(stream); ReadWriteIOUtils.write(count, stream); + ReadWriteIOUtils.write(tiesResolvingScheme.isPresent(), stream); + if (tiesResolvingScheme.isPresent()) { + tiesResolvingScheme.get().serialize(stream); + } } public static LimitNode deserialize(ByteBuffer byteBuffer) { long count = ReadWriteIOUtils.readLong(byteBuffer); + Optional tiesResolvingScheme = ReadWriteIOUtils.readBool(byteBuffer) + ? Optional.of(OrderingScheme.deserialize(byteBuffer)) + : Optional.empty(); PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer); - return new LimitNode(planNodeId, null, count, null); + return new LimitNode(planNodeId, null, count, tiesResolvingScheme); } @Override @@ -115,16 +123,19 @@ public long getCount() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; LimitNode limitNode = (LimitNode) o; - return Objects.equal(count, limitNode.count); + return count == limitNode.count && Objects.equal(tiesResolvingScheme, limitNode.tiesResolvingScheme); } @Override public int hashCode() { - return Objects.hashCode(super.hashCode(), count); + return Objects.hashCode(super.hashCode(), count, tiesResolvingScheme); } @Override