docs: public Result run(Database database, Relation<O> relation) {
      // Get a distance and kNN query instance.
      DistanceQuery<O> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
      KNNQuery<O> knnQuery = database.getKNNQuery(distQuery, k);
  
      // No query set - use original database.
      if(queries == null) {
        final DBIDs sample = DBIDUtil.randomSample(relation.getDBIDs(), sampling, random);
        FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
        int hash = 0;
        MeanVariance mv = new MeanVariance(), mvdist = new MeanVariance();
        for(DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
          KNNList knns = knnQuery.getKNNForDBID(iditer, k);
          int ichecksum = 0;
          for(DBIDIter it = knns.iter(); it.valid(); it.advance()) {
            ichecksum += DBIDUtil.asInteger(it);
          }
          hash = Util.mixHashCodes(hash, ichecksum);
          mv.put(knns.size());
          mvdist.put(knns.getKNNDistance());
          LOG.incrementProcessed(prog);
        }
        LOG.ensureCompleted(prog);
        if(LOG.isStatistics()) {
          LOG.statistics("Result hashcode: " + hash);
          LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
          if(mvdist.getCount() > 0) {
            LOG.statistics("Mean k-distance: " + mvdist.getMean() + " +- " + mvdist.getNaiveStddev());
          }
        }
      }
      else {
        // Separate query set.
        TypeInformation res = getDistanceFunction().getInputTypeRestriction();
        MultipleObjectsBundle bundle = queries.loadData();
        int col = -1;
        for(int i = 0; i < bundle.metaLength(); i++) {
          if(res.isAssignableFromType(bundle.meta(i))) {
            col = i;
            break;
          }
        }
        if(col < 0) {
          throw new IncompatibleDataException("No compatible data type in query input was found. Expected: " + res.toString());
        }
        // Random sampling is a bit of hack, sorry.
        // But currently, we don't (yet) have an "integer random sample" function.
        DBIDRange sids = DBIDUtil.generateStaticDBIDRange(bundle.dataLength());
        final DBIDs sample = DBIDUtil.randomSample(sids, sampling, random);
        FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
        int hash = 0;
        MeanVariance mv = new MeanVariance(), mvdist = new MeanVariance();
        for(DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
          int off = sids.binarySearch(iditer);
          assert (off >= 0);
          @SuppressWarnings("unchecked")
          O o = (O) bundle.data(off, col);
          KNNList knns = knnQuery.getKNNForObject(o, k);
          int ichecksum = 0;
          for(DBIDIter it = knns.iter(); it.valid(); it.advance()) {
            ichecksum += DBIDUtil.asInteger(it);
          }
          hash = Util.mixHashCodes(hash, ichecksum);
          mv.put(knns.size());
          mvdist.put(knns.getKNNDistance());
          LOG.incrementProcessed(prog);
        }
        LOG.ensureCompleted(prog);
        if(LOG.isStatistics()) {
          LOG.statistics("Result hashcode: " + hash);
          LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
          if(mvdist.getCount() > 0) {
            LOG.statistics("Mean k-distance: " + mvdist.getMean() + " +- " + mvdist.getNaiveStddev());
          }
        }
      }
      return null;
    }