Repository: sequelize/sequelize
File: src/dialects/abstract/query-generator.js (JavaScript)

Code before:
      result += this.quoteIdentifier(field.name);

      if (this.dialect.supports.index.collate && field.collate) {
        result += ` COLLATE ${this.quoteIdentifier(field.collate)}`;
      }

      if (this.dialect.supports.index.operator) {
        const operator = field.operator || options.operator;
        if (operator) {
          result += ` ${operator}`;
        }
      }

      if (this.dialect.supports.index.length > 0 && field.length > 0) {
        result += `(${field.length})`;
      }

      if (field.order) {
        result += ` ${field.order}`;
      }

      return result;
    });

    let includeSql;
    if (this.dialect.supports.index.include && options.include) {
      includeSql = options.include.map(column => this.quoteIdentifier(column));
    }

    if (!options.name) {
      // Mostly for cases where addIndex is called directly by the user without an options object (for example in migrations)
      // All calls that go through sequelize should already have a name
      options = Utils.nameIndex(options, options.prefix);
    }

    options = Model._conformIndex(options);

    if (!this.dialect.supports.index.type) {
      delete options.type;
    }

    if (options.where) {
      options.where = this.whereQuery(options.where);
    }

    const escapedTableName = typeof tableName === 'string' ? this.quoteIdentifiers(tableName) : this.quoteTable(tableName);

    const concurrently = this.dialect.supports.index.concurrently && options.concurrently ? 'CONCURRENTLY' : undefined;
    let ind;
    if (this.dialect.supports.indexViaAlter) {
      ind = [

Review comment (performance):
if `index.include` is not supported by this dialect and is specified, this should throw an error explaining that `include` is not supported

I know it's different to the other existing checks but we're changing that (slowly) to make the ORM more reliable

Code after:

    options = Model._conformIndex(options);

    if (!this.dialect.supports.index.type) {
      delete options.type;
    }

    if (options.where) {
      options.where = this.whereQuery(options.where);
    }

    const escapedTableName = this.quoteTable(tableName);

    const concurrently = this.dialect.supports.index.concurrently && options.concurrently ? 'CONCURRENTLY' : undefined;
    let ind;
    if (this.dialect.supports.indexViaAlter) {
      ind = [
        'ALTER TABLE',
        escapedTableName,
        concurrently,
        'ADD',
      ];
    } else {
      ind = ['CREATE'];
    }

    // DB2 incorrectly scopes the index if we don't specify the schema name,
    // which will cause it to error if another schema contains a table that uses an index with an identical name
    const escapedIndexName = tableName.schema && this.dialect.name === 'db2'
      // 'quoteTable' isn't the best name: it quotes any identifier.
      // in this case, the goal is to produce '"schema_name"."index_name"' to scope the index in this schema
      ? this.quoteTable({
        schema: tableName.schema,
        tableName: options.name,
      })
      : this.quoteIdentifiers(options.name);

    ind = ind.concat(
      options.unique ? 'UNIQUE' : '',
      options.type, 'INDEX',
      !this.dialect.supports.indexViaAlter ? concurrently : undefined,
      escapedIndexName,
      this.dialect.supports.index.using === 1 && options.using ? `USING ${options.using}` : '',
      !this.dialect.supports.indexViaAlter ? `ON ${escapedTableName}` : undefined,
      this.dialect.supports.index.using === 2 && options.using ? `USING ${options.using}` : '',
      `(${fieldsSql.join(', ')})`,
      this.dialect.supports.index.parser && options.parser ? `WITH PARSER ${options.parser}` : undefined,
      this.dialect.supports.index.include && options.include ? includeSql : undefined,
      this.dialect.supports.index.where && options.where ? options.where : undefined,
    );