You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hu...@apache.org on 2022/10/28 02:44:03 UTC

[iotdb] branch rel/0.13 updated: [To rel/0.13][IOTDB-4781] Implement NOT LIKE/REGEXP value filter (#7764)

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

hui pushed a commit to branch rel/0.13
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rel/0.13 by this push:
     new b51b4391de [To rel/0.13][IOTDB-4781] Implement NOT LIKE/REGEXP value filter (#7764)
b51b4391de is described below

commit b51b4391dea967c0a64544d208a32f5ea2faf244
Author: liuminghui233 <36...@users.noreply.github.com>
AuthorDate: Fri Oct 28 10:43:56 2022 +0800

    [To rel/0.13][IOTDB-4781] Implement NOT LIKE/REGEXP value filter (#7764)
---
 .../iotdb/db/integration/IoTDBFuzzyQueryIT.java    | 354 +++++++++++++--------
 .../iotdb/db/qp/logical/crud/LikeOperator.java     |  40 ++-
 .../iotdb/db/qp/logical/crud/RegexpOperator.java   |  40 ++-
 .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java    |   4 +-
 .../qp/strategy/optimizer/ConcatPathOptimizer.java |   6 +-
 .../iotdb/db/qp/physical/PhysicalPlanTest.java     |   3 +-
 .../iotdb/tsfile/read/filter/ValueFilter.java      |  38 ++-
 .../iotdb/tsfile/read/filter/operator/Like.java    |  22 +-
 .../iotdb/tsfile/read/filter/operator/Regexp.java  |  20 +-
 .../tsfile/read/filter/FilterSerializeTest.java    |   2 +-
 10 files changed, 338 insertions(+), 191 deletions(-)

diff --git a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBFuzzyQueryIT.java b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBFuzzyQueryIT.java
index 9e99f60e9e..a1ecc0df5f 100644
--- a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBFuzzyQueryIT.java
+++ b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBFuzzyQueryIT.java
@@ -37,176 +37,207 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
 import static org.junit.Assert.fail;
 
 @Category({LocalStandaloneTest.class})
 public class IoTDBFuzzyQueryIT {
-  private static List<String> sqls = new ArrayList<>();
+
+  private static final List<String> sqls =
+      Arrays.asList(
+          "SET STORAGE GROUP TO root.t1",
+          "CREATE TIMESERIES root.t1.wf01.wt01.status WITH DATATYPE=TEXT, ENCODING=PLAIN",
+          "CREATE TIMESERIES root.t1.wf01.wt01.temperature WITH DATATYPE=FLOAT, ENCODING=RLE",
+          "CREATE TIMESERIES root.t1.wf01.wt02.status WITH DATATYPE=TEXT, ENCODING=PLAIN",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465600000,'1',12.1)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465660000,'14',13.1)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465720000,'616',5.5)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465780000,'626',8.1)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465840000,'6116',4.3)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465900000,'6%16',10.3)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465960000,'8[sS]*',11.3)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466020000,'%123',18.3)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466080000,'123%',18.3)",
+          "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466090000,'\\\\',10.3)",
+          "insert into root.t1.wf01.wt02 (time,status) values (1509465600000,'14')");
+
   private static Connection connection;
 
   @BeforeClass
   public static void setUp() throws Exception {
-    initCreateSQLStatement();
     EnvironmentUtils.envSetUp();
+
+    Class.forName(Config.JDBC_DRIVER_NAME);
+    connection =
+        DriverManager.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+
     insertData();
   }
 
   @AfterClass
   public static void tearDown() throws Exception {
-    close();
+    connection.close();
     EnvironmentUtils.cleanEnv();
   }
 
-  private static void close() {
-    if (Objects.nonNull(connection)) {
-      try {
-        connection.close();
-      } catch (Exception e) {
-        e.printStackTrace();
+  private static void insertData() {
+    try (Statement statement = connection.createStatement(); ) {
+      for (String sql : sqls) {
+        statement.execute(sql);
       }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
     }
   }
 
-  private static void initCreateSQLStatement() {
-    sqls.add("SET STORAGE GROUP TO root.t1");
-    sqls.add("CREATE TIMESERIES root.t1.wf01.wt01.status WITH DATATYPE=TEXT, ENCODING=PLAIN");
-    sqls.add("CREATE TIMESERIES root.t1.wf01.wt01.temperature WITH DATATYPE=FLOAT, ENCODING=RLE");
-    sqls.add("CREATE TIMESERIES root.t1.wf01.wt02.status WITH DATATYPE=TEXT, ENCODING=PLAIN");
-
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465600000,'1',12.1)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465660000,'14',13.1)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465720000,'616',5.5)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465780000,'626',8.1)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465840000,'6116',4.3)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465900000,'6%16',10.3)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509465960000,'8[sS]*',11.3)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466020000,'%123',18.3)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466080000,'123%',18.3)");
-    sqls.add(
-        "insert into root.t1.wf01.wt01 (time,status,temperature) values (1509466090000,'\\\\',10.3)");
-    sqls.add("insert into root.t1.wf01.wt02 (time,status) values (1509465600000,'14')");
-  }
+  @Test
+  public void testLike() {
+    try (Statement statement = connection.createStatement(); ) {
+      boolean hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '1'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("1", outputResultStr(statement.getResultSet()));
 
-  private static void insertData() throws ClassNotFoundException, SQLException {
-    Class.forName(Config.JDBC_DRIVER_NAME);
-    connection =
-        DriverManager.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
-    Statement statement = connection.createStatement();
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,6116,6%16,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '1%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("1,14,123%", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '%1%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,6116,6%16,%123,123%", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '6%6'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("616,626,6116,6%16", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '1_'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("14", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '6_1%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("6116,6%16", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '6\\%%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("6%16", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '\\%%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("%123", outputResultStr(statement.getResultSet()));
 
-    for (String sql : sqls) {
-      statement.execute(sql);
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '%\\%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("123%", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where status like '%\\\\\\\\%'");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("\\", outputResultStr(statement.getResultSet()));
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
     }
-    statement.close();
   }
 
   @Test
-  public void testLike() throws SQLException {
-    Statement st0 = connection.createStatement();
-    boolean hasResultSet =
-        st0.execute("select status from root.t1.wf01.wt01 where status like '1'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("1", outputResultStr(st0.getResultSet()));
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals(
-        "1,14,616,626,6116,6%16,8[sS]*,%123,123%,\\", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '1%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("1,14,123%", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '%1%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("1,14,616,6116,6%16,%123,123%", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '6%6'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("616,626,6116,6%16", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '1_'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("14", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '6_1%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("6116,6%16", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '6\\%%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("6%16", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '\\%%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("%123", outputResultStr(st0.getResultSet()));
-
-    hasResultSet = st0.execute("select status from root.t1.wf01.wt01 where status like '%\\%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("123%", outputResultStr(st0.getResultSet()));
-
-    hasResultSet =
-        st0.execute("select status from root.t1.wf01.wt01 where status like '%\\\\\\\\%'");
-    Assert.assertTrue(hasResultSet);
-    Assert.assertEquals("\\", outputResultStr(st0.getResultSet()));
-  }
+  public void testNotLike() {
+    try (Statement statement = connection.createStatement(); ) {
+      boolean hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '1')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "14,616,626,6116,6%16,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
 
-  @Test(expected = Exception.class)
-  public void testLikeNonTextCloumn() throws SQLException {
-    Statement st1 = connection.createStatement();
-    st1.execute("select * from root.t1.wf01.wt01 where temperature like '1'");
-  }
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("", outputResultStr(statement.getResultSet()));
 
-  private String outputResultStr(ResultSet resultSet) throws SQLException {
-    StringBuilder resultBuilder = new StringBuilder();
-    while (resultSet.next()) {
-      resultBuilder.append(resultSet.getString(2)).append(",");
-    }
-    String result = resultBuilder.toString();
-    return result.substring(0, result.length() - 1);
-  }
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '1%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "616,626,6116,6%16,8[sS]*,%123,\\", outputResultStr(statement.getResultSet()));
 
-  private List<Integer> checkHeader(
-      ResultSetMetaData resultSetMetaData, String expectedHeaderStrings, int[] expectedTypes)
-      throws SQLException {
-    String[] expectedHeaders = expectedHeaderStrings.split(",");
-    Map<String, Integer> expectedHeaderToTypeIndexMap = new HashMap<>();
-    for (int i = 0; i < expectedHeaders.length; ++i) {
-      expectedHeaderToTypeIndexMap.put(expectedHeaders[i], i);
-    }
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '%1%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("626,8[sS]*,\\", outputResultStr(statement.getResultSet()));
 
-    List<Integer> actualIndexToExpectedIndexList = new ArrayList<>();
-    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
-      Integer typeIndex = expectedHeaderToTypeIndexMap.get(resultSetMetaData.getColumnName(i));
-      Assert.assertNotNull(typeIndex);
-      Assert.assertEquals(expectedTypes[typeIndex], resultSetMetaData.getColumnType(i));
-      actualIndexToExpectedIndexList.add(typeIndex);
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '6%6')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals("1,14,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '1_')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,616,626,6116,6%16,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '6_1%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '6\\%%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,6116,8[sS]*,%123,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '\\%%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,6116,6%16,8[sS]*,123%,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute("select status from root.t1.wf01.wt01 where not (status like '%\\%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,6116,6%16,8[sS]*,%123,\\", outputResultStr(statement.getResultSet()));
+
+      hasResultSet =
+          statement.execute(
+              "select status from root.t1.wf01.wt01 where not (status like '%\\\\\\\\%')");
+      Assert.assertTrue(hasResultSet);
+      Assert.assertEquals(
+          "1,14,616,626,6116,6%16,8[sS]*,%123,123%", outputResultStr(statement.getResultSet()));
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
     }
-    return actualIndexToExpectedIndexList;
   }
 
   @Test
-  public void selectLikeAlignByDevice() throws ClassNotFoundException {
+  public void selectLikeAlignByDevice() {
     String[] retArray =
         new String[] {"1509465660000,root.t1.wf01.wt01,14,", "1509465600000,root.t1.wf01.wt02,14"};
 
-    Class.forName(Config.JDBC_DRIVER_NAME);
-    try (Connection connection =
-            DriverManager.getConnection(
-                Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
-        Statement statement = connection.createStatement()) {
+    try (Statement statement = connection.createStatement()) {
       boolean hasResultSet =
           statement.execute(
               "select status from root.t1.wf01.wt0* where status like '14%' align by device");
@@ -236,14 +267,14 @@ public class IoTDBFuzzyQueryIT {
         }
         Assert.assertEquals(2, cnt);
       }
-    } catch (Exception e) {
+    } catch (SQLException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
   }
 
   @Test
-  public void selectRegexpAlignByDevice() throws ClassNotFoundException {
+  public void selectRegexpAlignByDevice() {
     String[] retArray =
         new String[] {
           "1509465600000,root.t1.wf01.wt01,1,",
@@ -252,11 +283,7 @@ public class IoTDBFuzzyQueryIT {
           "1509465600000,root.t1.wf01.wt02,14,"
         };
 
-    Class.forName(Config.JDBC_DRIVER_NAME);
-    try (Connection connection =
-            DriverManager.getConnection(
-                Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
-        Statement statement = connection.createStatement()) {
+    try (Statement statement = connection.createStatement()) {
       boolean hasResultSet =
           statement.execute(
               "select status from root.t1.wf01.wt0* where status regexp '^1.*' align by device");
@@ -286,9 +313,64 @@ public class IoTDBFuzzyQueryIT {
         }
         Assert.assertEquals(4, cnt);
       }
-    } catch (Exception e) {
+    } catch (SQLException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
   }
+
+  @Test
+  public void testLikeNonTextColumn() {
+    try (Statement statement = connection.createStatement()) {
+      statement.execute("select * from root.t1.wf01.wt01 where temperature like '1'");
+      fail("no exception!");
+    } catch (SQLException e) {
+      Assert.assertTrue(
+          e.getMessage(),
+          e.getMessage().contains("Unsupported type: [FLOAT]. Only TEXT is supported in 'Like'"));
+    }
+  }
+
+  @Test
+  public void testRegexpNonTextColumn() {
+    try (Statement statement = connection.createStatement()) {
+      statement.execute("select * from root.t1.wf01.wt01 where temperature regexp '1'");
+      fail("no exception!");
+    } catch (SQLException e) {
+      Assert.assertTrue(
+          e.getMessage(),
+          e.getMessage().contains("Unsupported type: [FLOAT]. Only TEXT is supported in 'Regexp'"));
+    }
+  }
+
+  private String outputResultStr(ResultSet resultSet) throws SQLException {
+    StringBuilder resultBuilder = new StringBuilder();
+    while (resultSet.next()) {
+      resultBuilder.append(resultSet.getString(2)).append(",");
+    }
+    String result = resultBuilder.toString();
+    if (result.isEmpty()) {
+      return result;
+    }
+    return result.substring(0, result.length() - 1);
+  }
+
+  private List<Integer> checkHeader(
+      ResultSetMetaData resultSetMetaData, String expectedHeaderStrings, int[] expectedTypes)
+      throws SQLException {
+    String[] expectedHeaders = expectedHeaderStrings.split(",");
+    Map<String, Integer> expectedHeaderToTypeIndexMap = new HashMap<>();
+    for (int i = 0; i < expectedHeaders.length; ++i) {
+      expectedHeaderToTypeIndexMap.put(expectedHeaders[i], i);
+    }
+
+    List<Integer> actualIndexToExpectedIndexList = new ArrayList<>();
+    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+      Integer typeIndex = expectedHeaderToTypeIndexMap.get(resultSetMetaData.getColumnName(i));
+      Assert.assertNotNull(typeIndex);
+      Assert.assertEquals(expectedTypes[typeIndex], resultSetMetaData.getColumnType(i));
+      actualIndexToExpectedIndexList.add(typeIndex);
+    }
+    return actualIndexToExpectedIndexList;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/LikeOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/LikeOperator.java
index 9183205230..1dd1e47151 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/LikeOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/LikeOperator.java
@@ -38,12 +38,14 @@ import static org.apache.iotdb.tsfile.file.metadata.enums.TSDataType.TEXT;
 /** fuzzy query structure LikeOperator. */
 public class LikeOperator extends FunctionOperator {
 
+  private boolean not;
   protected String value;
 
-  public LikeOperator(FilterType filterType, PartialPath path, String value) {
+  public LikeOperator(FilterType filterType, PartialPath path, String value, boolean not) {
     super(filterType);
     this.singlePath = path;
     this.value = value;
+    this.not = not;
     isLeaf = true;
     isSingle = true;
   }
@@ -68,19 +70,20 @@ public class LikeOperator extends FunctionOperator {
               singlePath,
               (value.startsWith("'") && value.endsWith("'"))
                   ? value.substring(1, value.length() - 1)
-                  : value);
+                  : value,
+              not);
     }
     return new Pair<>(ret, singlePath.getFullPath());
   }
 
   private static class Like {
     public static <T extends Comparable<T>> IUnaryExpression getUnaryExpression(
-        PartialPath path, String value) {
-      return new SingleSeriesExpression(path, ValueFilter.like(value));
+        PartialPath path, String value, boolean not) {
+      return new SingleSeriesExpression(path, ValueFilter.like(value, not));
     }
 
-    public <T extends Comparable<T>> Filter getValueFilter(String value) {
-      return ValueFilter.like(value);
+    public <T extends Comparable<T>> Filter getValueFilter(String value, boolean not) {
+      return ValueFilter.like(value, not);
     }
   }
 
@@ -90,13 +93,13 @@ public class LikeOperator extends FunctionOperator {
     for (int i = 0; i < spaceNum; i++) {
       sc.addTail("  ");
     }
-    sc.addTail(singlePath.getFullPath(), getFilterSymbol(), value, ", single\n");
+    sc.addTail(singlePath.getFullPath(), getFilterSymbol(), not, value, ", single\n");
     return sc.toString();
   }
 
   @Override
   public LikeOperator copy() {
-    LikeOperator ret = new LikeOperator(this.filterType, singlePath.clone(), value);
+    LikeOperator ret = new LikeOperator(this.filterType, singlePath.clone(), value, not);
     ret.isLeaf = isLeaf;
     ret.isSingle = isSingle;
     ret.pathSet = pathSet;
@@ -115,20 +118,35 @@ public class LikeOperator extends FunctionOperator {
       return false;
     }
     LikeOperator that = (LikeOperator) o;
-    return Objects.equals(value, that.value);
+    return Objects.equals(value, that.value) && not == that.not;
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(super.hashCode(), singlePath, value);
+    return Objects.hash(super.hashCode(), singlePath, value, not);
   }
 
   @Override
   public String toString() {
-    return "[" + singlePath.getFullPath() + getFilterSymbol() + value + "]";
+    return "["
+        + singlePath.getFullPath()
+        + (not ? " NOT " : " ")
+        + getFilterSymbol()
+        + " "
+        + value
+        + "]";
+  }
+
+  @Override
+  public void reverseFunc() {
+    not = !not;
   }
 
   public String getValue() {
     return value;
   }
+
+  public boolean isNot() {
+    return not;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/RegexpOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/RegexpOperator.java
index 4551f09f2a..a411de9a8e 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/RegexpOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/RegexpOperator.java
@@ -37,12 +37,14 @@ import static org.apache.iotdb.tsfile.file.metadata.enums.TSDataType.TEXT;
 
 public class RegexpOperator extends FunctionOperator {
 
+  private boolean not;
   protected String value;
 
-  public RegexpOperator(FilterType filterType, PartialPath path, String value) {
+  public RegexpOperator(FilterType filterType, PartialPath path, String value, boolean not) {
     super(filterType);
     this.singlePath = path;
     this.value = value;
+    this.not = not;
     isLeaf = true;
     isSingle = true;
   }
@@ -67,19 +69,20 @@ public class RegexpOperator extends FunctionOperator {
               singlePath,
               (value.startsWith("'") && value.endsWith("'"))
                   ? value.substring(1, value.length() - 1)
-                  : value);
+                  : value,
+              not);
     }
     return new Pair<>(ret, singlePath.getFullPath());
   }
 
   private static class Regexp {
     public static <T extends Comparable<T>> IUnaryExpression getUnaryExpression(
-        PartialPath path, String value) {
-      return new SingleSeriesExpression(path, ValueFilter.regexp(value));
+        PartialPath path, String value, boolean not) {
+      return new SingleSeriesExpression(path, ValueFilter.regexp(value, not));
     }
 
-    public <T extends Comparable<T>> Filter getValueFilter(String value) {
-      return ValueFilter.regexp(value);
+    public <T extends Comparable<T>> Filter getValueFilter(String value, boolean not) {
+      return ValueFilter.regexp(value, not);
     }
   }
 
@@ -89,13 +92,13 @@ public class RegexpOperator extends FunctionOperator {
     for (int i = 0; i < spaceNum; i++) {
       sc.addTail("  ");
     }
-    sc.addTail(singlePath.getFullPath(), value, ", single\n");
+    sc.addTail(singlePath.getFullPath(), not, value, ", single\n");
     return sc.toString();
   }
 
   @Override
   public RegexpOperator copy() {
-    RegexpOperator ret = new RegexpOperator(this.filterType, singlePath.clone(), value);
+    RegexpOperator ret = new RegexpOperator(this.filterType, singlePath.clone(), value, not);
     ret.isLeaf = isLeaf;
     ret.isSingle = isSingle;
     ret.pathSet = pathSet;
@@ -114,20 +117,35 @@ public class RegexpOperator extends FunctionOperator {
       return false;
     }
     RegexpOperator that = (RegexpOperator) o;
-    return Objects.equals(value, that.value);
+    return Objects.equals(value, that.value) && not == that.not;
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(super.hashCode(), singlePath, value);
+    return Objects.hash(super.hashCode(), singlePath, value, not);
   }
 
   @Override
   public String toString() {
-    return "[" + singlePath.getFullPath() + value + "]";
+    return "["
+        + singlePath.getFullPath()
+        + (not ? " NOT " : " ")
+        + getFilterSymbol()
+        + " "
+        + value
+        + "]";
+  }
+
+  @Override
+  public void reverseFunc() {
+    not = !not;
   }
 
   public String getValue() {
     return value;
   }
+
+  public boolean isNot() {
+    return not;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 9b909b4aee..67ffe2efe3 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -2620,8 +2620,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
         throw new SQLParserException("Path is null, please check the sql.");
       }
       return ctx.REGEXP() != null
-          ? new RegexpOperator(FilterType.REGEXP, path, ctx.STRING_LITERAL().getText())
-          : new LikeOperator(FilterType.LIKE, path, ctx.STRING_LITERAL().getText());
+          ? new RegexpOperator(FilterType.REGEXP, path, ctx.STRING_LITERAL().getText(), false)
+          : new LikeOperator(FilterType.LIKE, path, ctx.STRING_LITERAL().getText(), false);
     } else {
       if (ctx.TIME() != null || ctx.TIMESTAMP() != null) {
         path = new PartialPath(SQLConstant.getSingleTimeArray());
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
index 756c27ac6b..4a23f77f6c 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
@@ -343,13 +343,15 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
               new LikeOperator(
                   operator.getFilterType(),
                   noStarPaths.get(i),
-                  ((LikeOperator) operator).getValue()));
+                  ((LikeOperator) operator).getValue(),
+                  ((LikeOperator) operator).isNot()));
         } else if (operator instanceof RegexpOperator) {
           currentNode.addChildOperator(
               new RegexpOperator(
                   operator.getFilterType(),
                   noStarPaths.get(i),
-                  ((RegexpOperator) operator).getValue()));
+                  ((RegexpOperator) operator).getValue(),
+                  ((RegexpOperator) operator).isNot()));
         } else {
           currentNode.addChildOperator(
               new BasicFunctionOperator(
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
index 76fe66a39c..a91e78b5d3 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
@@ -1443,7 +1443,8 @@ public class PhysicalPlanTest {
     PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
     IExpression queryFilter = ((RawDataQueryPlan) plan).getExpression();
     IExpression expect =
-        new SingleSeriesExpression(new Path("root.vehicle.d5", "s1"), ValueFilter.like("string*"));
+        new SingleSeriesExpression(
+            new Path("root.vehicle.d5", "s1"), ValueFilter.regexp("string*", false));
     assertEquals(expect.toString(), queryFilter.toString());
   }
 
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
index 3dcfbe94f8..c6bc55f34e 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
@@ -70,12 +70,12 @@ public class ValueFilter {
     return new ValueNotEq(value);
   }
 
-  public static <T extends Comparable<T>> ValueRegexp<T> regexp(String value) {
-    return new ValueRegexp(value);
+  public static <T extends Comparable<T>> ValueRegexp<T> regexp(String value, boolean not) {
+    return new ValueRegexp(value, not);
   }
 
-  public static <T extends Comparable<T>> ValueLike<T> like(String value) {
-    return new ValueLike(value);
+  public static <T extends Comparable<T>> ValueLike<T> like(String value, boolean not) {
+    return new ValueLike(value, not);
   }
 
   public static class ValueIn<T extends Comparable<T>> extends In<T> {
@@ -246,8 +246,8 @@ public class ValueFilter {
 
   public static class ValueRegexp<T extends Comparable<T>> extends Regexp<T> {
 
-    private ValueRegexp(String value) {
-      super(value, FilterType.VALUE_FILTER);
+    private ValueRegexp(String value, boolean not) {
+      super(value, FilterType.VALUE_FILTER, not);
     }
   }
 
@@ -255,21 +255,24 @@ public class ValueFilter {
 
     private final int index;
 
-    private VectorValueRegexp(String value, int index) {
-      super(value);
+    private VectorValueRegexp(String value, int index, boolean not) {
+      super(value, not);
       this.index = index;
     }
 
     public boolean satisfy(long time, TsPrimitiveType[] values) {
-      Object v = filterType == FilterType.TIME_FILTER ? time : values[index].getValue();
-      return this.value.equals(v);
+      if (filterType != FilterType.VALUE_FILTER) {
+        return false;
+      }
+      Object value = values[index].getValue();
+      return pattern.matcher(new MatcherInput(value.toString(), new AccessCount())).find() != not;
     }
   }
 
   public static class ValueLike<T extends Comparable<T>> extends Like<T> {
 
-    private ValueLike(String value) {
-      super(value, FilterType.VALUE_FILTER);
+    private ValueLike(String value, boolean not) {
+      super(value, FilterType.VALUE_FILTER, not);
     }
   }
 
@@ -277,14 +280,17 @@ public class ValueFilter {
 
     private final int index;
 
-    private VectorValueLike(String value, int index) {
-      super(value);
+    private VectorValueLike(String value, int index, boolean not) {
+      super(value, not);
       this.index = index;
     }
 
     public boolean satisfy(long time, TsPrimitiveType[] values) {
-      Object v = filterType == FilterType.TIME_FILTER ? time : values[index].getValue();
-      return this.value.equals(v);
+      if (filterType != FilterType.VALUE_FILTER) {
+        return false;
+      }
+      Object value = values[index].getValue();
+      return pattern.matcher(value.toString()).find() != not;
     }
   }
 }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Like.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Like.java
index fac3dfcf5b..7b7023d39a 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Like.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Like.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
@@ -45,15 +46,18 @@ public class Like<T extends Comparable<T>> implements Filter {
 
   protected Pattern pattern;
 
+  protected boolean not;
+
   private Like() {}
 
   /**
    * The main idea of this part comes from
    * https://codereview.stackexchange.com/questions/36861/convert-sql-like-to-regex/36864
    */
-  public Like(String value, FilterType filterType) {
+  public Like(String value, FilterType filterType, boolean not) {
     this.value = value;
     this.filterType = filterType;
+    this.not = not;
     try {
       String unescapeValue = unescapeString(value);
       String specialRegexStr = ".^$*+?{}[]|()";
@@ -94,7 +98,7 @@ public class Like<T extends Comparable<T>> implements Filter {
     if (filterType != FilterType.VALUE_FILTER) {
       return false;
     }
-    return pattern.matcher(value.toString()).find();
+    return pattern.matcher(value.toString()).find() != not;
   }
 
   @Override
@@ -109,7 +113,7 @@ public class Like<T extends Comparable<T>> implements Filter {
 
   @Override
   public Filter copy() {
-    return new Like(value, filterType);
+    return new Like(value, filterType, not);
   }
 
   @Override
@@ -118,6 +122,7 @@ public class Like<T extends Comparable<T>> implements Filter {
       outputStream.write(getSerializeId().ordinal());
       outputStream.write(filterType.ordinal());
       ReadWriteIOUtils.writeObject(value, outputStream);
+      ReadWriteIOUtils.write(not, outputStream);
     } catch (IOException ex) {
       throw new IllegalArgumentException("Failed to serialize outputStream of type:", ex);
     }
@@ -127,11 +132,20 @@ public class Like<T extends Comparable<T>> implements Filter {
   public void deserialize(ByteBuffer buffer) {
     filterType = FilterType.values()[buffer.get()];
     value = ReadWriteIOUtils.readString(buffer);
+    not = ReadWriteIOUtils.readBool(buffer);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    return o instanceof Like
+        && Objects.equals(((Like<?>) o).value, value)
+        && ((Like<?>) o).filterType == filterType
+        && ((Like<?>) o).not == not;
   }
 
   @Override
   public String toString() {
-    return filterType + " is " + value;
+    return filterType + (not ? " not like " : " like ") + value;
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Regexp.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Regexp.java
index 31e7260469..2ffed8a253 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Regexp.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Regexp.java
@@ -45,11 +45,14 @@ public class Regexp<T extends Comparable<T>> implements Filter {
 
   protected Pattern pattern;
 
+  protected boolean not;
+
   public Regexp() {}
 
-  public Regexp(String value, FilterType filterType) {
+  public Regexp(String value, FilterType filterType, boolean not) {
     this.value = value;
     this.filterType = filterType;
+    this.not = not;
     try {
       this.pattern = Pattern.compile(this.value);
     } catch (PatternSyntaxException e) {
@@ -67,7 +70,7 @@ public class Regexp<T extends Comparable<T>> implements Filter {
     if (filterType != FilterType.VALUE_FILTER) {
       return false;
     }
-    return pattern.matcher(new MatcherInput(value.toString(), new AccessCount())).find();
+    return pattern.matcher(new MatcherInput(value.toString(), new AccessCount())).find() != not;
   }
 
   @Override
@@ -82,7 +85,7 @@ public class Regexp<T extends Comparable<T>> implements Filter {
 
   @Override
   public Filter copy() {
-    return new Regexp(value, filterType);
+    return new Regexp(value, filterType, not);
   }
 
   @Override
@@ -91,6 +94,7 @@ public class Regexp<T extends Comparable<T>> implements Filter {
       outputStream.write(getSerializeId().ordinal());
       outputStream.write(filterType.ordinal());
       ReadWriteIOUtils.write(value, outputStream);
+      ReadWriteIOUtils.write(not, outputStream);
     } catch (IOException ex) {
       throw new IllegalArgumentException("Failed to serialize outputStream of type:", ex);
     }
@@ -107,18 +111,20 @@ public class Regexp<T extends Comparable<T>> implements Filter {
         throw new PatternSyntaxException("Regular expression error", value, e.getIndex());
       }
     }
+    not = ReadWriteIOUtils.readBool(buffer);
   }
 
   @Override
   public String toString() {
-    return filterType + " is " + value;
+    return filterType + (not ? " not regexp " : " regexp ") + value;
   }
 
   @Override
   public boolean equals(Object o) {
     return o instanceof Regexp
         && Objects.equals(((Regexp<?>) o).value, value)
-        && ((Regexp<?>) o).filterType == filterType;
+        && ((Regexp<?>) o).filterType == filterType
+        && ((Regexp<?>) o).not == not;
   }
 
   @Override
@@ -126,7 +132,7 @@ public class Regexp<T extends Comparable<T>> implements Filter {
     return FilterSerializeId.REGEXP;
   }
 
-  private static class AccessCount {
+  public static class AccessCount {
     private int count;
     private final int accessThreshold =
         TSFileDescriptor.getInstance().getConfig().getPatternMatchingThreshold();
@@ -138,7 +144,7 @@ public class Regexp<T extends Comparable<T>> implements Filter {
     }
   }
 
-  private static class MatcherInput implements CharSequence {
+  public static class MatcherInput implements CharSequence {
 
     private final CharSequence value;
 
diff --git a/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/FilterSerializeTest.java b/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/FilterSerializeTest.java
index 779e32d404..fc8e63a16f 100644
--- a/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/FilterSerializeTest.java
+++ b/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/FilterSerializeTest.java
@@ -48,7 +48,7 @@ public class FilterSerializeTest {
           ValueFilter.notEq(false),
           ValueFilter.in(new HashSet<>(Arrays.asList("a", "b")), false),
           ValueFilter.in(new HashSet<>(Arrays.asList("c", "d")), true),
-          ValueFilter.regexp("s.*"),
+          ValueFilter.regexp("s.*", false),
         };
     for (Filter filter : filters) {
       validateSerialization(filter);