private void compareIndexes()

in core/src/main/java/com/jetbrains/youtrackdb/internal/core/db/tool/DatabaseCompare.java [345:510]


  private void compareIndexes(EntityHelper.RIDMapper ridMapper) {
    listener.onMessage("\nStarting index comparison:");

    var ok = true;

    final var indexManagerOne = sessionOne.getSharedContext().getIndexManager();
    final var indexManagerTwo = sessionTwo.getSharedContext().getIndexManager();

    final var indexesOne = indexManagerOne.getIndexes();
    var indexesSizeOne = indexesOne.size();

    var indexesSizeTwo = indexManagerTwo.getIndexes().size();

    if (indexManagerTwo.getIndex(DatabaseImport.EXPORT_IMPORT_INDEX_NAME) != null) {
      indexesSizeTwo--;
    }

    if (indexesSizeOne != indexesSizeTwo) {
      ok = false;
      listener.onMessage("\n- ERR: Amount of indexes are different.");
      listener.onMessage("\n--- DB1: " + indexesSizeOne);
      listener.onMessage("\n--- DB2: " + indexesSizeTwo);
      listener.onMessage("\n");
      ++differences;
    }

    for (var indexOne : indexesOne) {
      final var indexName = indexOne.getName();
      if (excludeIndexes.contains(indexName)) {
        continue;
      }

      final var indexTwo = indexManagerTwo.getIndex(indexOne.getName());
      if (indexTwo == null) {
        ok = false;
        listener.onMessage("\n- ERR: Index " + indexOne.getName() + " is absent in DB2.");
        ++differences;
        continue;
      }

      if (!indexOne.getType().equals(indexTwo.getType())) {
        ok = false;
        listener.onMessage(
            "\n- ERR: Index types for index " + indexOne.getName() + " are different.");
        listener.onMessage("\n--- DB1: " + indexOne.getType());
        listener.onMessage("\n--- DB2: " + indexTwo.getType());
        listener.onMessage("\n");
        ++differences;
        continue;
      }

      if (!indexOne.getCollections().equals(indexTwo.getCollections())) {
        ok = false;
        listener.onMessage(
            "\n- ERR: Collections to index for index " + indexOne.getName() + " are different.");
        listener.onMessage("\n--- DB1: " + indexOne.getCollections());
        listener.onMessage("\n--- DB2: " + indexTwo.getCollections());
        listener.onMessage("\n");
        ++differences;
        continue;
      }

      if (indexOne.getDefinition() == null && indexTwo.getDefinition() != null) {
        // THIS IS NORMAL SINCE 3.0 DUE OF REMOVING OF INDEX WITHOUT THE DEFINITION,  THE IMPORTER
        // WILL CREATE THE DEFINITION
        listener.onMessage(
            "\n- WARN: Index definition for index " + indexOne.getName() + " for DB2 is not null.");
        continue;
      } else {
        if (indexOne.getDefinition() != null && indexTwo.getDefinition() == null) {
          ok = false;
          listener.onMessage(
              "\n- ERR: Index definition for index " + indexOne.getName() + " for DB2 is null.");
          ++differences;
          continue;
        } else {
          if (indexOne.getDefinition() != null
              && !indexOne.getDefinition().equals(indexTwo.getDefinition())) {
            ok = false;
            listener.onMessage(
                "\n- ERR: Index definitions for index " + indexOne.getName() + " are different.");
            listener.onMessage("\n--- DB1: " + indexOne.getDefinition());
            listener.onMessage("\n--- DB2: " + indexTwo.getDefinition());
            listener.onMessage("\n");
            ++differences;
            continue;
          }
        }
      }

      final var indexOneSize = indexOne.size(sessionOne);
      final var indexTwoSize = indexTwo.size(sessionTwo);

      if (indexOneSize != indexTwoSize) {
        ok = false;
        listener.onMessage(
            "\n- ERR: Amount of entries for index " + indexOne.getName() + " are different.");
        listener.onMessage("\n--- DB1: " + indexOneSize);
        listener.onMessage("\n--- DB2: " + indexTwoSize);
        listener.onMessage("\n");
        ++differences;
      }

      if (compareIndexMetadata) {
        final var metadataOne = indexOne.getMetadata();
        final var metadataTwo = indexTwo.getMetadata();

        if (metadataOne == null && metadataTwo != null) {
          ok = false;
          listener.onMessage(
              "\n- ERR: Metadata for index "
                  + indexOne.getName()
                  + " for DB1 is null but for DB2 is not.");
          listener.onMessage("\n");
          ++differences;
        } else {
          if (metadataOne != null && metadataTwo == null) {
            ok = false;
            listener.onMessage(
                "\n- ERR: Metadata for index "
                    + indexOne.getName()
                    + " for DB1 is not null but for DB2 is null.");
            listener.onMessage("\n");
            ++differences;
          } else {
            if (!Objects.equals(metadataOne, metadataTwo)) {
              ok = false;
              listener.onMessage(
                  "\n- ERR: Metadata for index "
                      + indexOne.getName()
                      + " for DB1 and for DB2 are different.");

              listener.onMessage("\n--- M1: " + metadataOne);
              listener.onMessage("\n--- M2: " + metadataTwo);

              listener.onMessage("\n");
              ++differences;
            }
          }
        }
      }

      if (((compareEntriesForAutomaticIndexes && !indexOne.getType().equals("DICTIONARY"))
          || !indexOne.isAutomatic())) {

        try (final var keyStream = indexOne.keyStream()) {
          final var indexKeyIteratorOne = keyStream.iterator();
          while (indexKeyIteratorOne.hasNext()) {
            final var indexKey = indexKeyIteratorOne.next();
            try (var indexOneStream = indexOne.getRids(sessionOne, indexKey)) {
              try (var indexTwoValue = indexTwo.getRids(sessionTwo, indexKey)) {
                differences +=
                    compareIndexStreams(
                        indexKey, indexOneStream, indexTwoValue, ridMapper, listener);
              }
            }
            ok = ok && differences > 0;
          }
        }
      }
    }

    if (ok) {
      listener.onMessage("OK");
    }
  }