public void invalidate(
      final String database, final String tableName, final List<PartialPath> patterns) {
    readWriteLock.writeLock().lock();
    try {
      final TableId firstKey = new TableId(database, tableName);
      if (patterns.isEmpty()) {
        dualKeyCache.invalidate(firstKey);
      } else {
        final List<PartialPath> multiMatchList =
            patterns.stream()
                .filter(
                    idFilter -> {
                      if (!idFilter.hasWildcard()) {
                        final IDeviceID deviceId =
                            IDeviceID.Factory.DEFAULT_FACTORY.create(
                                Arrays.copyOfRange(
                                    idFilter.getNodes(), 2, idFilter.getNodeLength()));
                        dualKeyCache.invalidate(firstKey, deviceId);
                        return false;
                      }
                      return true;
                    })
                .collect(Collectors.toList());

        dualKeyCache.invalidate(
            firstKey,
            deviceId -> {
              final String[] segments = (String[]) deviceId.getSegments();
              for (int i = 1; i < segments.length; ++i) {
                for (final PartialPath path : multiMatchList) {
                  final int pathIndex = i + 2;
                  if (path.getNodes()[pathIndex].equals(segments[i])
                      || path.getNodes()[pathIndex].equals(ONE_LEVEL_PATH_WILDCARD)
                          && ((ExtendedPartialPath) path).match(pathIndex, segments[i])) {
                    return true;
                  }
                }
              }
              return false;
            });
      }
    } finally {
      readWriteLock.writeLock().unlock();
    }
  }
Invalidate the last cache of one device.

@param database the device's database, without "root"
@param deviceId IDeviceID
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/cache/TableDeviceSchemaCache.java