docs: public String upgradeCatalogAsNeeded(InMemoryJarfile outputJar)
                      throws IOException
      {
          // getBuildInfoFromJar() performs some validation.
          String[] buildInfoLines = CatalogUtil.getBuildInfoFromJar(outputJar);
          String versionFromCatalog = buildInfoLines[0];
          // Set if an upgrade happens.
          String upgradedFromVersion = null;
  
          // Check if it's compatible (or the upgrade is being forced).
          // getConfig() may return null if it's being mocked for a test.
          if (   VoltDB.Configuration.m_forceCatalogUpgrade
              || !versionFromCatalog.equals(VoltDB.instance().getVersionString())) {
  
              // Patch the buildinfo.
              String versionFromVoltDB = VoltDB.instance().getVersionString();
              buildInfoLines[0] = versionFromVoltDB;
              buildInfoLines[1] = String.format("voltdb-auto-upgrade-to-%s", versionFromVoltDB);
              byte[] buildInfoBytes = StringUtils.join(buildInfoLines, "\n").getBytes();
              outputJar.put(CatalogUtil.CATALOG_BUILDINFO_FILENAME, buildInfoBytes);
  
              // Gather DDL files for re-compilation
              List<VoltCompilerReader> ddlReaderList = new ArrayList<>();
              Entry<String, byte[]> entry = outputJar.firstEntry();
              while (entry != null) {
                  String path = entry.getKey();
                  // ENG-12980: only look for auto-gen.ddl on root directory
                  if (AUTOGEN_DDL_FILE_NAME.equalsIgnoreCase(path)) {
                      ddlReaderList.add(new VoltCompilerJarFileReader(outputJar, path));
                      break;
                  }
                  entry = outputJar.higherEntry(entry.getKey());
              }
  
              if (ddlReaderList.size() == 0) {
                  // did not find auto generated DDL file during upgrade
                  throw new IOException("Could not find " + AUTOGEN_DDL_FILE_NAME + " in the catalog "
                          + "compiled by VoltDB " + versionFromCatalog);
              }
  
              // Use the in-memory jarfile-provided class loader so that procedure
              // classes can be found and copied to the new file that gets written.
              ClassLoader originalClassLoader = m_classLoader;
  
              // Compile and save the file to voltdbroot. Assume it's a test environment if there
              // is no catalog context available.
              String jarName = String.format("catalog-%s.jar", versionFromVoltDB);
              String textName = String.format("catalog-%s.out", versionFromVoltDB);
              CatalogContext catalogContext = VoltDB.instance().getCatalogContext();
              final String outputJarPath = (catalogContext != null
                      ? new File(VoltDB.instance().getVoltDBRootPath(), jarName).getPath()
                      : VoltDB.Configuration.getPathToCatalogForTest(jarName));
              // Place the compiler output in a text file in the same folder.
              final String outputTextPath = (catalogContext != null
                      ? new File(VoltDB.instance().getVoltDBRootPath(), textName).getPath()
                      : VoltDB.Configuration.getPathToCatalogForTest(textName));
              try {
                  m_classLoader = outputJar.getLoader();
  
                  consoleLog.info(String.format(
                          "Version %s catalog will be automatically upgraded to version %s.",
                          versionFromCatalog, versionFromVoltDB));
  
                  // Do the compilation work.
                  boolean success = compileInternalToFile(outputJarPath, null, null, ddlReaderList, outputJar);
  
                  // Sanitize the *.sql files in the jarfile so that only the autogenerated
                  // canonical DDL file will be used for future compilations
                  // Bomb out if we failed to generate the canonical DDL
                  if (success) {
                      boolean foundCanonicalDDL = false;
                      entry = outputJar.firstEntry();
                      while (entry != null) {
                          String path = entry.getKey();
                          if (path.toLowerCase().endsWith(".sql")) {
                              if (!path.toLowerCase().equals(AUTOGEN_DDL_FILE_NAME)) {
                                  outputJar.remove(path);
                              }
                              else {
                                  foundCanonicalDDL = true;
                              }
                          }
                          entry = outputJar.higherEntry(entry.getKey());
                      }
                      success = foundCanonicalDDL;
                  }
  
                  if (success) {
                      // Set up the return string.
                      upgradedFromVersion = versionFromCatalog;
                  }
  
                  // Summarize the results to a file.
                  // Briefly log success or failure and mention the output text file.
                  PrintStream outputStream = new PrintStream(outputTextPath);
                  try {
                      if (success) {
                          summarizeSuccess(outputStream, outputStream, outputJarPath);
                          consoleLog.info(String.format(
                                  "The catalog was automatically upgraded from " +
                                  "version %s to %s and saved to \"%s\". " +
                                  "Compiler output is available in \"%s\".",
                                  versionFromCatalog, versionFromVoltDB,
                                  outputJarPath, outputTextPath));
                      }
                      else {
                          summarizeErrors(outputStream, outputStream);
                          outputStream.close();
                          compilerLog.error("Catalog upgrade failed.");
                          compilerLog.info(String.format(
                                  "Had attempted to perform an automatic version upgrade of a " +
                                  "catalog that was compiled by an older %s version of VoltDB, " +
                                  "but the automatic upgrade failed. The cluster  will not be " +
                                  "able to start until the incompatibility is fixed. " +
                                  "Try re-compiling the catalog with the newer %s version " +
                                  "of the VoltDB compiler. Compiler output from the failed " +
                                  "upgrade is available in \"%s\".",
                                  versionFromCatalog, versionFromVoltDB, outputTextPath));
                          throw new IOException(String.format(
                                  "Catalog upgrade failed. You will need to recompile using voltdb compile."));
                      }
                  }
                  finally {
                      outputStream.close();
                  }
              }
              catch (IOException ioe) {
                  // Do nothing because this could come from the normal failure path
                  throw ioe;
              }
              catch (Exception e) {
                  compilerLog.error("Catalog upgrade failed with error:");
                  compilerLog.error(e.getMessage());
                  compilerLog.info(String.format(
                          "Had attempted to perform an automatic version upgrade of a " +
                          "catalog that was compiled by an older %s version of VoltDB, " +
                          "but the automatic upgrade failed. The cluster  will not be " +
                          "able to start until the incompatibility is fixed. " +
                          "Try re-compiling the catalog with the newer %s version " +
                          "of the VoltDB compiler. Compiler output from the failed " +
                          "upgrade is available in \"%s\".",
                          versionFromCatalog, versionFromVoltDB, outputTextPath));
                  throw new IOException(String.format(
                          "Catalog upgrade failed. You will need to recompile using voltdb compile."));
              }
              finally {
                  // Restore the original class loader
                  m_classLoader = originalClassLoader;
              }
          }
          return upgradedFromVersion;
      }