code: def read(self, n=-1):
          
          pos = self.tell()
          num_items_to_read = n if n != -1 else self.length - pos
          # calculate the position of the file pointer after data was read:
          new_pos = min(pos + num_items_to_read, self.length)
  
          if new_pos > self._current_lob_length:
              missing_num_items_to_read = new_pos - self._current_lob_length
              self._read_missing_lob_data_from_db(self._current_lob_length, missing_num_items_to_read)
          # reposition file pointer to original position as reading in IO buffer might have changed it
          self.seek(pos, SEEK_SET)
          return self.data.read(n)
docs: Read up to n items (bytes/chars) from the lob and return them.
          If n is -1 then all available data is returned.
          Might trigger further loading of data from the database if the number of items requested for
          reading is larger than what is currently buffered.