/**
   * Restore the row stored in the optional data of the log record.
   *
   * @exception IOException error reading from log stream
   * @exception StandardException Standard Derby error policy
   */
  public void restoreLoggedRow(Object[] row, LimitObjectInput in)
      throws StandardException, IOException {
    BasePage p = null;

    try {
      // the optional data is written by the page in the same format it
      // stores record on the page,
      // only a page knows how to restore a logged row back to a storable row
      // first get the page where the insert went even though the row may no
      // longer be there
      p = (BasePage) (getContainer().getPage(getPageId().getPageNumber()));

      // skip over the before and after image of the column, position the
      // input stream at the entire row
      p.skipField(in); // AI of the column
      p.skipField(in); // BI of the column

      p.restoreRecordFromStream(in, row);

      // RESOLVE: this returns the BI of the row, what we need is the AI
      // of the row.  We need to someone splice in the AI of the column
      // into the storable row.

    } finally {

      if (p != null) {
        p.unlatch();
        p = null;
      }
    }
  }
  /**
   * Restore field to its old value.
   *
   * @exception IOException Can be thrown by any of the methods of ObjectInput.
   * @exception StandardException Standard Derby policy.
   * @see LogicalPageOperation#undoMe
   */
  public void undoMe(
      Transaction xact,
      BasePage undoPage,
      int undoRecordId,
      LogInstant CLRInstant,
      LimitObjectInput in)
      throws StandardException, IOException {
    int slot = undoPage.findRecordById(undoRecordId, Page.FIRST_SLOT_NUMBER);

    if (SanityManager.DEBUG) {
      // if the record Id has changed, the page had better changed
      // this can only happen during recovery since in run time undo,
      // this resetRecordHandle gets called and this object have the new
      // page number and recordId
      if (undoRecordId != this.recordId)
        if (undoPage.getPageNumber() == getPageId().getPageNumber())
          SanityManager.THROWASSERT(
              "recordId changed from "
                  + this.recordId
                  + " to "
                  + undoRecordId
                  + " but page number did not change "
                  + undoPage.getPageNumber());

      if (slot == -1)
        SanityManager.THROWASSERT(
            "recordId " + undoRecordId + " not found on page " + undoPage.getPageNumber());
    }

    undoPage.skipField((java.io.ObjectInput) in); // skip the after image of the column
    undoPage.storeField(CLRInstant, slot, fieldId, in);
    undoPage.setAuxObject(null);
  }
  /**
   * restore the before image of the page
   *
   * @exception StandardException Standard Derby Error Policy
   * @exception IOException problem reading the complete log record from the input stream
   */
  public void restoreMe(
      Transaction xact, BasePage undoPage, LogInstant CLRInstant, LimitObjectInput in)
      throws StandardException, IOException {
    int slot = undoPage.findRecordById(recordId, Page.FIRST_SLOT_NUMBER);
    if (SanityManager.DEBUG) {
      if (!getPageId().equals(undoPage.getPageId()))
        SanityManager.THROWASSERT(
            "restoreMe cannot restore to a different page. "
                + "doMe page:"
                + getPageId()
                + " undoPage:"
                + undoPage.getPageId());
      if (slot != doMeSlot)
        SanityManager.THROWASSERT(
            "restoreMe cannot restore to a different slot. "
                + "doMe slot:"
                + doMeSlot
                + " undoMe slot: "
                + slot
                + " recordId:"
                + recordId);
    }

    undoPage.skipField(in); // skip the after image of the column
    undoPage.storeField(CLRInstant, slot, fieldId, in);
    undoPage.setAuxObject(null);
  }