This is an automated email from the ASF dual-hosted git repository.

jiangtian pushed a commit to branch fix_false_positive_deletion
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 0c4f8cb0ad2fb85e3dd6132e3a054ca1733b06f0
Author: Tian Jiang <[email protected]>
AuthorDate: Thu Nov 28 18:11:05 2024 +0800

    Fix that queries may retrieve false positive deletion
---
 .../relational/it/db/it/IoTDBDeletionTableIT.java  | 36 ++++++++++++++++++++--
 .../execution/fragment/QueryContext.java           | 15 +++++++--
 2 files changed, 46 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 3dd9672187b..6d2d591fed1 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
@@ -604,20 +604,50 @@ public class IoTDBDeletionTableIT {
       statement.execute("flush");
 
       statement.execute("delete from t" + testNum + " where id1 is NULL and 
time <= 1");
-      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + 
testNum)) {
+      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + testNum 
+ " order by time")) {
         assertTrue(set.next());
+        assertEquals(2, set.getLong("time"));
         assertTrue(set.next());
+        assertEquals(3, set.getLong("time"));
         assertFalse(set.next());
       }
 
       statement.execute("delete from t" + testNum + " where id2 is NULL");
-      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + 
testNum)) {
+      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + testNum 
+ " order by time")) {
         assertTrue(set.next());
+        assertEquals(2, set.getLong("time"));
         assertFalse(set.next());
       }
 
       statement.execute("delete from t" + testNum);
-      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + 
testNum)) {
+      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + testNum 
+ " order by time")) {
+        assertFalse(set.next());
+      }
+
+      statement.execute("drop table t" + testNum);
+    }
+  }
+
+  @Test
+  public void testEmptyString() throws SQLException {
+    int testNum = 15;
+    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("insert into t" + testNum + " (time, id2, s1) values 
(2, '', 2)");
+      statement.execute("insert into t" + testNum + " (time, id2, s1) values 
(3, NULL, 3)");
+      statement.execute("flush");
+
+      statement.execute("delete from t" + testNum + " where id2 is null");
+      try (ResultSet set = statement.executeQuery("SELECT * FROM t" + testNum 
+ " order by time")) {
+        assertTrue(set.next());
+        assertEquals(1, set.getLong("time"));
+        assertTrue(set.next());
+        assertEquals(3, set.getLong("time"));
         assertFalse(set.next());
       }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/QueryContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/QueryContext.java
index 28d4e14703b..566e998d2c4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/QueryContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/QueryContext.java
@@ -40,6 +40,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Collectors;
 
 /** QueryContext contains the shared information with in a query. */
 public class QueryContext {
@@ -117,8 +118,18 @@ public class QueryContext {
       return Collections.emptyList();
     }
 
-    return ModificationUtils.sortAndMerge(
-        getAllModifications(tsFileResource).getOverlapped(deviceID, 
measurement));
+    List<ModEntry> modEntries =
+        ModificationUtils.sortAndMerge(
+            getAllModifications(tsFileResource).getOverlapped(deviceID, 
measurement));
+    if (deviceID.isTableModel()) {
+      // the pattern tree has false-positive for table model deletion, so we 
do a further
+      //     filtering
+      modEntries =
+          modEntries.stream()
+              .filter(mod -> mod.affects(deviceID) && mod.affects(measurement))
+              .collect(Collectors.toList());
+    }
+    return modEntries;
   }
 
   public List<ModEntry> getPathModifications(TsFileResource tsFileResource, 
IDeviceID deviceID)

Reply via email to