private ColumnVector[] handleOriginalFile(
      BitSet selectedBitSet, ColumnVector[] innerRecordIdColumnVector) throws IOException {
    /*
     * If there are deletes and reading original file, we must produce synthetic ROW_IDs in order
     * to see if any deletes apply
     */
    boolean needSyntheticRowId =
        needSyntheticRowIds(true, !deleteEventRegistry.isEmpty(), rowIdProjected);
    if(needSyntheticRowId) {
      assert syntheticProps != null : "" + syntheticProps;
      assert syntheticProps.getRowIdOffset() >= 0 : "" + syntheticProps;
      assert syntheticProps.getBucketProperty() >= 0 : "" + syntheticProps;
      if(innerReader == null) {
        throw new IllegalStateException(getClass().getName() + " requires " +
          org.apache.orc.RecordReader.class +
          " to handle original files that require ROW__IDs: " + rootPath);
      }
      /**
       * {@link RecordIdentifier#getWriteId()}
       */
      recordIdColumnVector.fields[0].noNulls = true;
      recordIdColumnVector.fields[0].isRepeating = true;
      ((LongColumnVector)recordIdColumnVector.fields[0]).vector[0] = syntheticProps.getSyntheticWriteId();
      /**
       * This is {@link RecordIdentifier#getBucketProperty()}
       * Also see {@link BucketCodec}
       */
      recordIdColumnVector.fields[1].noNulls = true;
      recordIdColumnVector.fields[1].isRepeating = true;
      ((LongColumnVector)recordIdColumnVector.fields[1]).vector[0] = syntheticProps.getBucketProperty();
      /**
       * {@link RecordIdentifier#getRowId()}
       */
      recordIdColumnVector.fields[2].noNulls = true;
      recordIdColumnVector.fields[2].isRepeating = false;
      long[] rowIdVector = ((LongColumnVector)recordIdColumnVector.fields[2]).vector;
      for(int i = 0; i < vectorizedRowBatchBase.size; i++) {
        //baseReader.getRowNumber() seems to point at the start of the batch todo: validate
        rowIdVector[i] = syntheticProps.getRowIdOffset() + innerReader.getRowNumber() + i;
      }
      //Now populate a structure to use to apply delete events
      innerRecordIdColumnVector = new ColumnVector[OrcRecordUpdater.FIELDS];
      innerRecordIdColumnVector[OrcRecordUpdater.ORIGINAL_WRITEID] = recordIdColumnVector.fields[0];
      innerRecordIdColumnVector[OrcRecordUpdater.BUCKET] = recordIdColumnVector.fields[1];
      innerRecordIdColumnVector[OrcRecordUpdater.ROW_ID] = recordIdColumnVector.fields[2];
      //these are insert events so (original txn == current) txn for all rows
      innerRecordIdColumnVector[OrcRecordUpdater.CURRENT_WRITEID] = recordIdColumnVector.fields[0];
    }
    if(syntheticProps.getSyntheticWriteId() > 0) {
      //"originals" (written before table was converted to acid) is considered written by
      // writeid:0 which is always committed so there is no need to check wrt invalid write Ids
      //But originals written by Load Data for example can be in base_x or delta_x_x so we must
      //check if 'x' is committed or not evn if ROW_ID is not needed in the Operator pipeline.
      if (needSyntheticRowId) {
        findRecordsWithInvalidWriteIds(innerRecordIdColumnVector,
            vectorizedRowBatchBase.size, selectedBitSet);
      } else {
        /*since ROW_IDs are not needed we didn't create the ColumnVectors to hold them but we
        * still have to check if the data being read is committed as far as current
        * reader (transactions) is concerned.  Since here we are reading 'original' schema file,
        * all rows in it have been created by the same txn, namely 'syntheticProps.syntheticWriteId'
        */
        if (!validWriteIdList.isWriteIdValid(syntheticProps.getSyntheticWriteId())) {
          selectedBitSet.clear(0, vectorizedRowBatchBase.size);
        }
      }
    }
    return innerRecordIdColumnVector;
  }
There are 2 types of schema from the {@link #baseReader} that this handles.  In the case
the data was written to a transactional table from the start, every row is decorated with
transaction related info and looks like &lt;op, owid, writerId, rowid, cwid, &lt;f1, ... fn&gt;&gt;.

The other case is when data was written to non-transactional table and thus only has the user
data: &lt;f1, ... fn&gt;.  Then this table was then converted to a transactional table but the data
files are not changed until major compaction.  These are the "original" files.

In this case we may need to decorate the outgoing data with transactional column values at
read time.  (It's done somewhat out of band via VectorizedRowBatchCtx - ask Teddy Choi).
The "owid, writerId, rowid" columns represent {@link RecordIdentifier}.  They are assigned
each time the table is read in a way that needs to project {@link VirtualColumn#ROWID}.
Major compaction will attach these values to each row permanently.
It's critical that these generated column values are assigned exactly the same way by each
read of the same row and by the Compactor.
See {@link MRCompactor} and
{@link OrcRawRecordMerger.OriginalReaderPairToCompact} for the Compactor read path.
(Longer term should make compactor use this class)

This only decorates original rows with metadata if something above is requesting these values
or if there are Delete events to apply.

@return false where there is no more data, i.e. {@code value} is empty
ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java