protected List<ObjectValuePair<String, IndexMetadata>> getIndexesSQL(
      ClassLoader classLoader, String tableName) throws IOException {

    if (!PortalClassLoaderUtil.isPortalClassLoader(classLoader)) {
      List<ObjectValuePair<String, IndexMetadata>> objectValuePairs = new ArrayList<>();

      try (InputStream is = classLoader.getResourceAsStream("META-INF/sql/indexes.sql");
          Reader reader = new InputStreamReader(is);
          UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(reader)) {

        String line = null;

        while ((line = unsyncBufferedReader.readLine()) != null) {
          line = line.trim();

          if (line.isEmpty()) {
            continue;
          }

          IndexMetadata indexMetadata = IndexMetadataFactoryUtil.createIndexMetadata(line);

          if (tableName.equals(indexMetadata.getTableName())) {
            objectValuePairs.add(new ObjectValuePair<>(line, indexMetadata));
          }
        }
      }

      return objectValuePairs;
    }

    if (!_portalIndexesSQL.isEmpty()) {
      return _portalIndexesSQL.get(tableName);
    }

    try (InputStream is =
            classLoader.getResourceAsStream(
                "com/liferay/portal/tools/sql/dependencies/indexes.sql");
        Reader reader = new InputStreamReader(is);
        UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(reader)) {

      String line = null;

      while ((line = unsyncBufferedReader.readLine()) != null) {
        line = line.trim();

        if (line.isEmpty()) {
          continue;
        }

        IndexMetadata indexMetadata = IndexMetadataFactoryUtil.createIndexMetadata(line);

        List<ObjectValuePair<String, IndexMetadata>> objectValuePairs =
            _portalIndexesSQL.get(indexMetadata.getTableName());

        if (objectValuePairs == null) {
          objectValuePairs = new ArrayList<>();

          _portalIndexesSQL.put(indexMetadata.getTableName(), objectValuePairs);
        }

        objectValuePairs.add(new ObjectValuePair<>(line, indexMetadata));
      }
    }

    return _portalIndexesSQL.get(tableName);
  }
  protected void alter(Class<?> tableClass, Alterable... alterables) throws Exception {

    try (LoggingTimer loggingTimer = new LoggingTimer()) {
      Field tableNameField = tableClass.getField("TABLE_NAME");

      String tableName = (String) tableNameField.get(null);

      DatabaseMetaData databaseMetaData = connection.getMetaData();

      try (ResultSet rs1 = databaseMetaData.getPrimaryKeys(null, null, tableName);
          ResultSet rs2 =
              databaseMetaData.getIndexInfo(
                  null, null, normalizeName(tableName, databaseMetaData), false, false)) {

        Set<String> primaryKeyNames = new HashSet<>();

        while (rs1.next()) {
          String primaryKeyName = StringUtil.toUpperCase(rs1.getString("PK_NAME"));

          if (primaryKeyName != null) {
            primaryKeyNames.add(primaryKeyName);
          }
        }

        Map<String, Set<String>> columnNamesMap = new HashMap<>();

        while (rs2.next()) {
          String indexName = StringUtil.toUpperCase(rs2.getString("INDEX_NAME"));

          if ((indexName == null) || primaryKeyNames.contains(indexName)) {

            continue;
          }

          Set<String> columnNames = columnNamesMap.get(indexName);

          if (columnNames == null) {
            columnNames = new HashSet<>();

            columnNamesMap.put(indexName, columnNames);
          }

          columnNames.add(StringUtil.toUpperCase(rs2.getString("COLUMN_NAME")));
        }

        for (Alterable alterable : alterables) {
          for (Map.Entry<String, Set<String>> entry : columnNamesMap.entrySet()) {

            if (alterable.shouldDropIndex(entry.getValue())) {
              runSQL("drop index " + entry.getKey() + " on " + tableName);
            }
          }

          runSQL(alterable.getSQL(tableName));

          List<ObjectValuePair<String, IndexMetadata>> objectValuePairs =
              getIndexesSQL(tableClass.getClassLoader(), tableName);

          if (objectValuePairs == null) {
            continue;
          }

          for (ObjectValuePair<String, IndexMetadata> objectValuePair : objectValuePairs) {

            IndexMetadata indexMetadata = objectValuePair.getValue();

            if (alterable.shouldAddIndex(Arrays.asList(indexMetadata.getColumnNames()))) {

              runSQLTemplateString(objectValuePair.getKey(), false, true);
            }
          }
        }
      } catch (SQLException sqle) {
        if (_log.isWarnEnabled()) {
          _log.warn("Fallback to recreating the table", sqle);
        }

        Field tableColumnsField = tableClass.getField("TABLE_COLUMNS");
        Field tableSQLCreateField = tableClass.getField("TABLE_SQL_CREATE");
        Field tableSQLAddIndexesField = tableClass.getField("TABLE_SQL_ADD_INDEXES");

        upgradeTable(
            tableName,
            (Object[][]) tableColumnsField.get(null),
            (String) tableSQLCreateField.get(null),
            (String[]) tableSQLAddIndexesField.get(null));
      }
    }
  }