This is an automated email from the ASF dual-hosted git repository. jiangtian pushed a commit to branch fix_delete_with_null_deviceId in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit e82aacfb64c366e24546934655475fd91fca9101 Author: Tian Jiang <[email protected]> AuthorDate: Wed Nov 27 10:08:35 2024 +0800 Fix query failure if a table deletion involves deviceId with null --- .../relational/it/db/it/IoTDBDeletionTableIT.java | 21 +++++++++++++++++ .../iotdb/db/metadata/path/PatternTreeMapTest.java | 27 +++++++++++++++++++--- .../org/apache/iotdb/commons/path/PartialPath.java | 3 ++- .../apache/iotdb/commons/path/PatternTreeMap.java | 2 +- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java index 1b25695c318..57e7692fda1 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java @@ -570,6 +570,27 @@ public class IoTDBDeletionTableIT { cleanData(testNum); } + @Test + public void testDeviceIdWithNull() throws SQLException { + int testNum = 14; + try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + Statement statement = connection.createStatement()) { + statement.execute("use test"); + statement.execute( + "create table t" + testNum + " (id1 string id, id2 string id, s1 int32 measurement)"); + // id1 is null for this record + statement.execute("insert into t" + testNum + " (time, id2, s1) values (1, '1', 1)"); + statement.execute("flush"); + statement.execute("delete from t" + testNum); + + try (ResultSet set = statement.executeQuery("SELECT * FROM t" + testNum)) { + assertFalse(set.next()); + } + + statement.execute("drop table t" + testNum); + } + } + @Ignore @Test public void testDeletionWritePerformance() throws SQLException, IOException { diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/path/PatternTreeMapTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/path/PatternTreeMapTest.java index 3292eb8ca86..e32b3c9f5bc 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/path/PatternTreeMapTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/path/PatternTreeMapTest.java @@ -22,12 +22,17 @@ import org.apache.iotdb.commons.exception.IllegalPathException; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.commons.path.PatternTreeMap; +import org.apache.iotdb.db.storageengine.dataregion.modification.DeletionPredicate; +import org.apache.iotdb.db.storageengine.dataregion.modification.IDPredicate.NOP; import org.apache.iotdb.db.storageengine.dataregion.modification.ModEntry; +import org.apache.iotdb.db.storageengine.dataregion.modification.TableDeletionEntry; import org.apache.iotdb.db.storageengine.dataregion.modification.TreeDeletionEntry; import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory; import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory.ModsSerializer; import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory.StringSerializer; +import org.apache.tsfile.file.metadata.IDeviceID.Factory; +import org.apache.tsfile.read.common.TimeRange; import org.junit.Assert; import org.junit.Test; @@ -37,6 +42,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class PatternTreeMapTest { @Test @@ -213,12 +221,25 @@ public class PatternTreeMapTest { new TreeDeletionEntry(new MeasurementPath("root.sg1.d1.*.d3.s4"), 4, 6))); } + @Test + public void testDeviceIdWithNull() { + PatternTreeMap<ModEntry, ModsSerializer> patternTreeMap = + PatternTreeMapFactory.getModsPatternTreeMap(); + ModEntry modEntry = + new TableDeletionEntry(new DeletionPredicate("table1", new NOP()), new TimeRange(0, 100)); + patternTreeMap.append(modEntry.keyOfPatternTree(), modEntry); + List<ModEntry> result = + patternTreeMap.getOverlapped( + Factory.DEFAULT_FACTORY.create(new String[] {"table1", null, "id2"}), "s1"); + assertEquals(Collections.singletonList(modEntry), result); + } + private <T> void checkOverlapped( PatternTreeMap<T, ?> patternTreeMap, PartialPath partialPath, List<T> expectedList) { Set<T> resultSet = new HashSet<>(patternTreeMap.getOverlapped(partialPath)); Assert.assertEquals(expectedList.size(), resultSet.size()); for (T o : expectedList) { - Assert.assertTrue(resultSet.contains(o)); + assertTrue(resultSet.contains(o)); } } @@ -234,7 +255,7 @@ public class PatternTreeMapTest { Set<T> actualSubSet = new HashSet<>(actualList.get(i)); Assert.assertEquals(expectedSubList.size(), actualSubSet.size()); for (T o : expectedSubList) { - Assert.assertTrue(actualSubSet.contains(o)); + assertTrue(actualSubSet.contains(o)); } } } @@ -244,7 +265,7 @@ public class PatternTreeMapTest { Set<T> resultSet = new HashSet<>(patternTreeMap.getDeviceOverlapped(devicePath)); Assert.assertEquals(expectedList.size(), resultSet.size()); for (T o : expectedList) { - Assert.assertTrue(resultSet.contains(o)); + assertTrue(resultSet.contains(o)); } } } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java index d03e4af88b4..f703096e025 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java @@ -72,7 +72,8 @@ public class PartialPath extends Path implements Comparable<Path>, Cloneable { System.arraycopy(tableNameSegments, 0, nodes, 0, tableNameSegments.length); // copy non-table-name segments for (int i = 0; i < device.segmentNum() - 1; i++) { - nodes[i + tableNameSegments.length] = device.segment(i + 1).toString(); + nodes[i + tableNameSegments.length] = + device.segment(i + 1) != null ? device.segment(i + 1).toString() : null; } this.fullPath = getFullPath(); } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java index 9f8fd569040..99216d10f45 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java @@ -143,7 +143,7 @@ public class PatternTreeMap<V, VSerializer extends PathPatternNode.Serializer<V> // TODO change this way PartialPath devicePath; try { - devicePath = new PartialPath(deviceID.toString()); + devicePath = new PartialPath(deviceID); } catch (IllegalPathException e) { throw new RuntimeException(e); }
