<commit_before>import * as knex from 'knex';
import {Query} from './Query';
import {Mapping, JoinColumn} from './Mapping';
import {Scope, Entity} from './Scope';
import {Hydrator} from './Hydrator';
import {Having} from './Criteria/Having';
import {Where} from './Criteria/Where';
import {On} from './Criteria/On';

export class QueryBuilder<T> {
  /**
   * @type {Query}
   */
  private query: Query;

  /**
   * @type {boolean}
   */
  private prepared: boolean = false;

  /**
   * @type {string}
   */
  private alias: string;

  /**
   * @type {Scope}
   */
  private entityManager: Scope;

  /**
   * @type {{}}
   */
  private statement: knex.QueryBuilder;

  /**
   * @type {Array}
   */
  private selects: Array<any> = [];

  /**
   * @type {{}]
   */
  private appliedPrimaryKeys: {[key: string]: string} = {};

  /**
   * @type {Array}
   */
  private groupBys: Array<{groupBy: string | Array<string>}> = [];

  /**
   * @type {Array}
   */
  private orderBys: Array<{orderBy: string | Array<string> | Object, direction: string | null}> = [];

  /**
   * @type {Mapping}
   */
  private mapping: Mapping<T>;

  /**
   * @type {Where}
   */
  private whereCriteria: Where;

  /**
   * @type {On}
   */
  private onCriteria;

  /**
   * @type {Having}
   */
  private havingCriteria: Having;

  /**
   * @type {{}}
   */
  private mappings: {[key: string]: Mapping<Entity>};

  /**
   * @type {string[]}
   */
  private functions: Array<string> = ['sum', 'count', 'max', 'min', 'avg'];

  /**
   * @type {string[]}
   */
  private singleJoinTypes: Array<string> = [Mapping.RELATION_ONE_TO_ONE, Mapping.RELATION_MANY_TO_ONE];

  /**
   * @type {Hydrator}
   */
  private hydrator: Hydrator;

  /**
   * @type {{}}
   */
  private aliased: {} = {};

  /**
   * Construct a new QueryBuilder.
   *
   * @param {Scope}             entityManager
   * @param {knex.QueryBuilder} statement
   * @param {Mapping}           mapping
   * @param {string}            alias
   */
  public constructor(entityManager: Scope, statement: knex.QueryBuilder, mapping: Mapping<T>, alias: string) {
    this.alias          = alias;
    this.mappings       = {[alias]: mapping};
    this.statement      = statement;
    this.whereCriteria  = new Where(this.statement, mapping, this.mappings);
    this.havingCriteria = new Having(this.statement, mapping, this.mappings);
    this.onCriteria     = new On(this.statement, mapping, this.mappings);
    this.entityManager  = entityManager;
    this.hydrator       = new Hydrator(entityManager);
    this.query          = new Query(statement, this.hydrator);

    this.hydrator.addRecipe(null, alias, this.mappings[alias]);
  }

  /**
   * Create an alias.
   *
   * @param {string} target
   *
   * @returns {string}
   */
  public createAlias(target: string): string {
    this.aliased[target] = this.aliased[target] || 0;

    return target + this.aliased[target]++;
  }

  /**
   * Perform a join.
   *
   * @param {string} joinMethod
   * @param {string} column
   * @param {string} targetAlias
   *
   * @returns {QueryBuilder}
   */
  public makeJoin(joinMethod: string, column: string, targetAlias: string): this {
    column                     = column.indexOf('.') > -1 ? column : `${this.alias}.${column}`;
    let [alias, property]      = column.split('.');
    let owningMapping          = this.mappings[alias];
    let join                   = owningMapping.getField(property).relationship;
    this.mappings[targetAlias] = Mapping.forEntity(this.entityManager.resolveEntityReference(join.targetEntity));
    let targetMapping          = this.mappings[targetAlias];
    let joinType               = this.singleJoinTypes.indexOf(join.type) > -1 ? 'single' : 'collection';
    let joinColumn             = owningMapping.getJoinColumn(property);
    let owning                 = alias;
    let inversed               = targetAlias;

    this.hydrator.addRecipe(alias, targetAlias, targetMapping, joinType, property);

    if (join.type === Mapping.RELATION_MANY_TO_MANY) {
      let joinTable;<commit_msg>refactor(QueryBuilder): add relation validation<commit_after>import * as knex from 'knex';
import {Query} from './Query';
import {Mapping, JoinColumn} from './Mapping';
import {Scope, Entity} from './Scope';
import {Hydrator} from './Hydrator';
import {Having} from './Criteria/Having';
import {Where} from './Criteria/Where';
import {On} from './Criteria/On';

export class QueryBuilder<T> {
  /**
   * @type {Query}
   */
  private query: Query;

  /**
   * @type {boolean}
   */
  private prepared: boolean = false;

  /**
   * @type {string}
   */
  private alias: string;

  /**
   * @type {Scope}
   */
  private entityManager: Scope;

  /**
   * @type {{}}
   */
  private statement: knex.QueryBuilder;

  /**
   * @type {Array}
   */
  private selects: Array<any> = [];

  /**
   * @type {{}]
   */
  private appliedPrimaryKeys: {[key: string]: string} = {};

  /**
   * @type {Array}
   */
  private groupBys: Array<{groupBy: string | Array<string>}> = [];

  /**
   * @type {Array}
   */
  private orderBys: Array<{orderBy: string | Array<string> | Object, direction: string | null}> = [];

  /**
   * @type {Mapping}
   */
  private mapping: Mapping<T>;

  /**
   * @type {Where}
   */
  private whereCriteria: Where;

  /**
   * @type {On}
   */
  private onCriteria;

  /**
   * @type {Having}
   */
  private havingCriteria: Having;

  /**
   * @type {{}}
   */
  private mappings: {[key: string]: Mapping<Entity>};

  /**
   * @type {string[]}
   */
  private functions: Array<string> = ['sum', 'count', 'max', 'min', 'avg'];

  /**
   * @type {string[]}
   */
  private singleJoinTypes: Array<string> = [Mapping.RELATION_ONE_TO_ONE, Mapping.RELATION_MANY_TO_ONE];

  /**
   * @type {Hydrator}
   */
  private hydrator: Hydrator;

  /**
   * @type {{}}
   */
  private aliased: {} = {};

  /**
   * Construct a new QueryBuilder.
   *
   * @param {Scope}             entityManager
   * @param {knex.QueryBuilder} statement
   * @param {Mapping}           mapping
   * @param {string}            alias
   */
  public constructor(entityManager: Scope, statement: knex.QueryBuilder, mapping: Mapping<T>, alias: string) {
    this.alias          = alias;
    this.mappings       = {[alias]: mapping};
    this.statement      = statement;
    this.whereCriteria  = new Where(this.statement, mapping, this.mappings);
    this.havingCriteria = new Having(this.statement, mapping, this.mappings);
    this.onCriteria     = new On(this.statement, mapping, this.mappings);
    this.entityManager  = entityManager;
    this.hydrator       = new Hydrator(entityManager);
    this.query          = new Query(statement, this.hydrator);

    this.hydrator.addRecipe(null, alias, this.mappings[alias]);
  }

  /**
   * Create an alias.
   *
   * @param {string} target
   *
   * @returns {string}
   */
  public createAlias(target: string): string {
    this.aliased[target] = this.aliased[target] || 0;

    return target + this.aliased[target]++;
  }

  /**
   * Perform a join.
   *
   * @param {string} joinMethod
   * @param {string} column
   * @param {string} targetAlias
   *
   * @returns {QueryBuilder}
   */
  public makeJoin(joinMethod: string, column: string, targetAlias: string): this {
    column                     = column.indexOf('.') > -1 ? column : `${this.alias}.${column}`;
    let [alias, property]      = column.split('.');
    let owningMapping          = this.mappings[alias];
    let field;

    if (property) {
      field = owningMapping.getField(property, true);
    }

    if (!field || !field.relationship) {
      throw new Error(
        'Invalid relation supplied for join. Property not found on entity, or relation not defined. ' +
        'Are you registering the joins in the wrong order?'
      );
    }

    let join                   = field.relationship;
    this.mappings[targetAlias] = Mapping.forEntity(this.entityManager.resolveEntityReference(join.targetEntity));
    let targetMapping          = this.mappings[targetAlias];
    let joinType               = this.singleJoinTypes.indexOf(join.type) > -1 ? 'single' : 'collection';
    let joinColumn             = owningMapping.getJoinColumn(property);
    let owning                 = alias;
    let inversed               = targetAlias;

    this.hydrator.addRecipe(alias, targetAlias, targetMapping, joinType, property);

    if (join.type === Mapping.RELATION_MANY_TO_MANY) {
      let joinTable;
{'fraction_non_alphanumeric': 0.15537659876835622, 'fraction_numerical': 0.0007105637138796779, 'mean_word_length': 2.6167023554603857, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5768374', 'n_tokens_mistral': 2721, 'n_tokens_neox': 2631, 'n_words': 610}