@Override
  public TsBlock next() throws Exception {
    TsBlock tsBlock = deviceOperator.nextWithTimer();
    if (tsBlock == null) {
      return null;
    }
    // fill existing columns
    Column[] newValueColumns = new Column[dataTypes.size()];
    for (int i = 0; i < deviceColumnIndex.size(); i++) {
      newValueColumns[deviceColumnIndex.get(i)] = tsBlock.getColumn(i);
    }
    // construct device column
    newValueColumns[0] = new RunLengthEncodedColumn(binaryColumn, tsBlock.getPositionCount());
    // construct other null columns
    for (int i = 0; i < dataTypes.size(); i++) {
      if (newValueColumns[i] == null) {
        newValueColumns[i] = NullColumn.create(dataTypes.get(i), tsBlock.getPositionCount());
      }
    }
    return new TsBlock(tsBlock.getPositionCount(), tsBlock.getTimeColumn(), newValueColumns);
  }
The {@link SingleDeviceViewOperator} plays a similar role with {@link DeviceViewOperator} of
adding a device column to current resultSet.

<p>Different from {@link DeviceViewOperator} which merge the resultSet from different devices,
{@link SingleDeviceViewOperator} only focuses on one single device, the goal of it is to add a
device view. It's just a transition and won't change the way data flows.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/SingleDeviceViewOperator.java