text: 'use strict';
  
  const createPivotJoin = (qb, joinTable, alias, tragetMeta) => {
    const joinAlias = qb.getAlias();
    qb.join({
      alias: joinAlias,
      referencedTable: joinTable.name,
      referencedColumn: joinTable.joinColumn.name,
      rootColumn: joinTable.joinColumn.referencedColumn,
      rootTable: alias,
      on: joinTable.on,
    });
  
    const subAlias = qb.getAlias();
    qb.join({
      alias: subAlias,
      referencedTable: tragetMeta.tableName,
      referencedColumn: joinTable.inverseJoinColumn.referencedColumn,
      rootColumn: joinTable.inverseJoinColumn.name,
      rootTable: joinAlias,
    });
  
    return subAlias;
  };
  
  const createJoin = (ctx, { alias, attributeName, attribute }) => {
    const { db, qb } = ctx;
  
    if (attribute.type !== 'relation') {
      throw new Error(`Cannot join on non relational field ${attributeName}`);
    }
  
    const tragetMeta = db.metadata.get(attribute.target);
  
    const joinColumn = attribute.joinColumn;
  
    if (joinColumn) {
      const subAlias = qb.getAlias();
      qb.join({
        alias: subAlias,
        referencedTable: tragetMeta.tableName,
        referencedColumn: joinColumn.referencedColumn,
        rootColumn: joinColumn.name,
        rootTable: alias,
      });
      return subAlias;
    }
  
    const joinTable = attribute.joinTable;
    if (joinTable) {
      return createPivotJoin(qb, joinTable, alias, tragetMeta);
    }
  
    return alias;
  };
  
  // TODO: toColumnName for orderBy & on
  const applyJoin = (qb, join) => {
    const {
      method = 'leftJoin',
      alias,
      referencedTable,
      referencedColumn,
      rootColumn,
      rootTable = qb.alias,
      on,
      orderBy,
    } = join;
  
    qb[method](`${referencedTable} as ${alias}`, inner => {
      inner.on(`${rootTable}.${rootColumn}`, `${alias}.${referencedColumn}`);
  
      if (on) {
        for (const key in on) {
          inner.onVal(`${alias}.${key}`, on[key]);
        }
      }
    });
  
    if (orderBy) {
      Object.keys(orderBy).forEach(column => {
        const direction = orderBy[column];
        qb.orderBy(`${alias}.${column}`, direction);
      });
    }
  };
  
  const applyJoins = (qb, joins) => joins.forEach(join => applyJoin(qb, join));
  
  module.exports = {
    createJoin,
    createPivotJoin,
    applyJoins,
    applyJoin,
  };
  