All files / src/rules index_completely_contained.ts

100% Statements 72/72
100% Branches 19/19
100% Functions 6/6
100% Lines 72/72

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 721x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11088x 11088x 11088x 11088x 33121x 33121x 33121x 33121x 33121x 33121x 33121x 11088x 11088x 244x 244x 11088x 11088x 10568x 10568x 11088x 11088x 244x 244x 11088x 11088x 329x 306x 306x 23x 23x 329x 21x 21x 2x 2x 329x 3x 3x 5x 3x 3x 2x 2x 2x 5x 3x 1x 1x 1x 3x 5x 1x 1x 1x 1x 5x 3x 2x 2x 2x 11088x 11088x
import {BasicRuleConfig} from "./_basic_rule_config";
import {IObject} from "../objects/_iobject";
import {IRule, RuleTag} from "./_irule";
import {Issue} from "../issue";
import {Position} from "../position";
import * as Objects from "../objects";
 
export class IndexCompletelyContainedConf extends BasicRuleConfig {
}
 
export class IndexCompletelyContained implements IRule {
  private conf = new IndexCompletelyContainedConf();
 
  public getMetadata() {
    return {
      key: "index_completely_contained",
      title: "Check if database table indexes are completely contained",
      shortDescription: `If indexes are completely contained in other indexes, they can be removed to improve performance.`,
      tags: [RuleTag.Performance, RuleTag.SingleFile],
    };
  }
 
  public initialize() {
    return this;
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: IndexCompletelyContainedConf) {
    this.conf = conf;
  }
 
  public run(obj: IObject): Issue[] {
    if (!(obj instanceof Objects.Table)) {
      return [];
    }
 
    const indexes = obj.getSecondaryIndexes();
    if (indexes === undefined || indexes.length === 0) {
      return [];
    }
 
    const issues: Issue[] = [];
    for (let i = 0; i < indexes.length; i++) {
      const indexA = indexes[i];
      for (let j = 0; j < indexes.length; j++) {
        if (i === j) {
          continue;
        }
        const indexB = indexes[j];
 
        let contained = true;
        for (const field of indexA.fields) {
          if (indexB.fields.indexOf(field) === -1) {
            contained = false;
            break;
          }
        }
        if (contained) {
          const position = new Position(1, 1);
          const message = `Index "${indexA.name}" is completely contained in index "${indexB.name}"`;
          issues.push(Issue.atPosition(obj.getFiles()[0], position, message, this.getMetadata().key, this.conf.severity));
        }
      }
    }
 
    return issues;
  }
 
}