Repository navigation
Fix NPE in ALIGN BY DEVICE queries when a device's predicate is always true - #19009
Merged
JackieTien97 merged 1 commit intoOct 24, 2026
Merged
Conversation
…s true In a tree-model ALIGN BY DEVICE query, the WHERE predicate is bound and simplified per device. When it becomes TRUE for a device, for example because it references a series that the device does not have (`s2 IS NULL`, `NOT (s2 > 5)`), analyzeDeviceToWhere stores null as that device's where expression to mean "no value filter". analyzeDeviceToSource passed that null to searchSourceExpressions, so the query failed with a NullPointerException (305). Skip null where expressions in analyzeDeviceToSource, as analyzeSource already does for queries without ALIGN BY DEVICE. LogicalPlanVisitor already plans a null where expression as no filter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
In a tree-model
ALIGN BY DEVICEquery, theWHEREpredicate is bound and simplified per device.When the predicate of a device simplifies to
TRUE,AnalyzeVisitor#analyzeDeviceToWherestoresnullas that device's where expression, which means "no value filter". This happens, for example,when the predicate references a series that the device does not have: the series is bound to
NullOperand, sos2 IS NULLbecomesnull IS NULL(TRUE) andNOT (s2 > 5)becomesNOT (null > 5)(TRUE).AnalyzeVisitor#analyzeDeviceToSourcedid not skip thesenullentries and passed them toExpressionAnalyzer.searchSourceExpressions, so the query failed:Reproduce:
The
nullconvention came with predicate simplification in b93cd04, which made thenon-
ALIGN BY DEVICEcounterpart (analyzeSource) skip anullwhere expression but missedanalyzeDeviceToSource. The other consumers of the per-device where expressions already handlenull:LogicalPlanVisitorplans it as "no filter", and the removal inanalyzeSelectisnull-safe.
Found while reviewing #18982, but independent of it: it also fails on master with a predicate that
contains no
NOT, and the two changes merge cleanly.Changes
AnalyzeVisitor#analyzeDeviceToSource: skip devices whose where expression isnull, asanalyzeSourcedoes, so their source expressions come only from the selected expressions.AnalyzeTest: a device whoseIS NULL/NOTpredicate becomesTRUE, and a mix of deviceswhere one device keeps its real filter.
DataQueryLogicalPlannerTest: only the device with a real predicate gets aFilterNode.IoTDBNullOperandIT: raw, time-filtered and aggregationALIGN BY DEVICEqueries on a seriesthat does not exist.
IoTDBAlignByDeviceIT(also runs as2IT/3IT/4IT): one device filtered by its own serieswhile the other device's predicate is always true, for raw and aggregation queries.
Verification
from
AnalyzeVisitor.analyzeDeviceToSource.mvn verify -pl iotdb-core/datanode,integration-test -am -P with-integration-tests -Dtest='org/apache/iotdb/db/queryengine/plan/**/*Test.java, !org/apache/iotdb/db/queryengine/plan/relational/**' -Dit.test=IoTDBNullOperandIT,IoTDBAlignByDeviceIT,IoTDBAlignByDevice2IT,IoTDBAlignByDevice3IT,IoTDBAlignByDevice4ITAnalyzeTest30/30,DataQueryLogicalPlannerTest14/14IoTDBNullOperandIT8/8,IoTDBAlignByDeviceIT/2IT/3IT/4IT22/22 eachqueryengine.planunit tests in that run show no new failures. FourPowerMock load test classes fail locally only because
user_encrypt_tokenis set in my shell;they fail the same way on master, and that is fixed separately in Fix datanode PowerMock tests failing when user_encrypt_token is set #19008.
🤖 Generated with Claude Code