docs: public FieldList move(int iRelPosition) throws DBException
      {
          if ((m_iRecordStatus & DBConstants.RECORD_NEXT_PENDING) == DBConstants.RECORD_NEXT_PENDING)
              if (iRelPosition == DBConstants.NEXT_RECORD)
          {
              m_iRecordStatus = DBConstants.RECORD_NORMAL;
              this.getRecord().handleValidRecord(); // Display Fields
              int iErrorCode = this.getRecord().handleRecordChange(DBConstants.MOVE_NEXT_TYPE);
              if (iErrorCode != DBConstants.NORMAL_RETURN)
                  throw new DatabaseException(iErrorCode);
              return this.getCurrentTable().getRecord();  // Special case - last call was hasNext()
          }
          if ((m_iRecordStatus & DBConstants.RECORD_PREVIOUS_PENDING) == DBConstants.RECORD_PREVIOUS_PENDING)
              if (iRelPosition == DBConstants.PREVIOUS_RECORD)
          {
              m_iRecordStatus = DBConstants.RECORD_NORMAL;
              this.getRecord().handleValidRecord(); // Display Fields
              int iErrorCode = this.getRecord().handleRecordChange(DBConstants.MOVE_NEXT_TYPE);
              if (iErrorCode != DBConstants.NORMAL_RETURN)
                  throw new DatabaseException(iErrorCode);
              return this.getCurrentTable().getRecord();  // Special case - last call was hasNext()
          }
          Record record = null;
          Object[] rgobjEnabledFields = null;
          try   {
              this.getRecord().setEditMode(Constants.EDIT_NONE);
  
              if (!this.isOpen())
                  this.open();    // Cool! It opens automatically.
              this.getRecord().setEditMode(Constants.EDIT_NONE);
  
              if (this.isTable())
              {
                  if (iRelPosition == DBConstants.NEXT_RECORD)
                      if (m_iRecordStatus == (DBConstants.RECORD_INVALID | DBConstants.RECORD_AT_BOF))
                          iRelPosition = DBConstants.FIRST_RECORD;    // After open, read first
                  if (iRelPosition == DBConstants.PREVIOUS_RECORD)
                      if (m_iRecordStatus == (DBConstants.RECORD_INVALID | DBConstants.RECORD_AT_BOF))
                          iRelPosition = DBConstants.LAST_RECORD;     // After open, read last
                  if ((iRelPosition == DBConstants.FIRST_RECORD) || (iRelPosition == DBConstants.LAST_RECORD))
                  {   // If this is a table, it can't handle starting and ending keys.. do it manually
                      KeyArea keyArea = this.getRecord().getKeyArea(-1);
                      if (keyArea != null) if (iRelPosition == DBConstants.FIRST_RECORD)
                      {
                          if (keyArea.isModified(DBConstants.START_SELECT_KEY))
                          {
                              keyArea.reverseKeyBuffer(null, DBConstants.START_SELECT_KEY);
                              boolean bFound =  this.getRecord().seek(">=");
                              if (bFound)
                                  record = this.getRecord();
                              else
                              {
                                  record = null;
                                  m_iRecordStatus |= DBConstants.RECORD_AT_EOF;
                              }
                              if (bFound) if (this.isTable())
                                  bFound = !this.isEOF();   // Do end criteria check
                              if (!bFound)
                              {
                                  record = null;
                                  m_iRecordStatus |= DBConstants.RECORD_AT_EOF;
                              }
                              return record;
                          }
                      }
                      else //   if (iRelPosition == DBConstants.LAST_RECORD)
                      {
                          if (keyArea.isModified(DBConstants.END_SELECT_KEY))
                          {
                              keyArea.reverseKeyBuffer(null, DBConstants.END_SELECT_KEY);
                              boolean bFound =  this.getRecord().seek("<=");
                              if (bFound)
                                  record = this.getRecord();
                              else
                              {
                                  record = null;
                                  m_iRecordStatus |= DBConstants.RECORD_AT_BOF;
                              }
                              if (bFound) if (this.isTable())
                                  bFound = !this.isBOF();   // Do end criteria check
                              if (!bFound)
                              {
                                  record = null;
                                  m_iRecordStatus |= DBConstants.RECORD_AT_BOF;
                              }
                              return record;
                          }
                      }
                  }
              }
  
              m_iRecordStatus = DBConstants.RECORD_INVALID;
              m_iRecordStatus = this.doMove(iRelPosition);    // Do the physical move next
  
              if (m_iRecordStatus == DBConstants.RECORD_NORMAL)
              {
                  rgobjEnabledFields = this.getRecord().setEnableFieldListeners(false);
                  this.dataToFields(this.getRecord());
                  this.getRecord().setEnableFieldListeners(rgobjEnabledFields);
              }
              if (this.isTable())
              {
                  if (this.isBOF())
                      m_iRecordStatus |= DBConstants.RECORD_AT_BOF; // At BOF
                  if (this.isEOF())
                      m_iRecordStatus |= DBConstants.RECORD_AT_EOF; // At EOF
              }
              if ((m_iRecordStatus & DBConstants.RECORD_AT_BOF) == DBConstants.RECORD_AT_BOF)
              {
                  this.getRecord().handleRecordChange(DBConstants.SELECT_EOF_TYPE); // Notify listeners that EOF was hit (Reading backward or readnext on an empty file)
                  record = null;
                  m_objectID = null;
                  m_dataSource = null;
                  return record;
              }
              if ((m_iRecordStatus & DBConstants.RECORD_AT_EOF) == DBConstants.RECORD_AT_EOF)
              {
                  this.getRecord().handleRecordChange(DBConstants.SELECT_EOF_TYPE); // Notify listeners that EOF was hit
                  record = null;
                  m_objectID = null;
                  m_dataSource = null;
                  return record;
              }
              this.getRecord().setEditMode(Constants.EDIT_CURRENT);
  
              // Special test for local criteria
              if (this.getRecord().handleLocalCriteria(null, false, null) == false)
              { // This record didn't pass the test, get the next one that matches
                  if ((iRelPosition > 0) || (iRelPosition == DBConstants.FIRST_RECORD))
                  {
                      if (iRelPosition == DBConstants.FIRST_RECORD)
                          iRelPosition = +1;
                      return this.move(iRelPosition);
                  }
                  if (iRelPosition == DBConstants.LAST_RECORD)
                      iRelPosition = -1;
                  return this.move(iRelPosition);
              }
              record = this.getRecord();  // m_CurrentRecord
  
          // Table will update m_dbEditMode to dbEditCurrent if found.
          } catch (DBException ex)    {
              if (rgobjEnabledFields != null)
                  this.getRecord().setEnableFieldListeners(rgobjEnabledFields);
              if (ex.getErrorCode() == DBConstants.INVALID_RECORD)
                  record = null;  // Special case (empty recordset)
              else
                  throw ex;
          }
          if (record != null)
          {
              this.getRecord().handleValidRecord(); // Display Fields
              int iErrorCode = this.getRecord().handleRecordChange(DBConstants.MOVE_NEXT_TYPE);
              if (iErrorCode != DBConstants.NORMAL_RETURN)
                  throw new DatabaseException(iErrorCode);
          }
          else
          {
              this.getRecord().handleNewRecord();     // Display Fields
          }
          return record;
      }