<commit_before>//  ███████╗ ██████╗ ██████╗  ██████╗ ███████╗    ███████╗████████╗ █████╗  ██████╗ ███████╗
//  ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝    ██╔════╝╚══██╔══╝██╔══██╗██╔════╝ ██╔════╝
//  █████╗  ██║   ██║██████╔╝██║  ███╗█████╗      ███████╗   ██║   ███████║██║  ███╗█████╗
//  ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝      ╚════██║   ██║   ██╔══██║██║   ██║██╔══╝
//  ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗    ███████║   ██║   ██║  ██║╚██████╔╝███████╗
//  ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝    ╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//
//  ████████╗██╗  ██╗██████╗ ███████╗███████╗     ██████╗ ██╗   ██╗███████╗██████╗ ██╗   ██╗
//  ╚══██╔══╝██║  ██║██╔══██╗██╔════╝██╔════╝    ██╔═══██╗██║   ██║██╔════╝██╔══██╗╚██╗ ██╔╝
//     ██║   ███████║██████╔╝█████╗  █████╗      ██║   ██║██║   ██║█████╗  ██████╔╝ ╚████╔╝
//     ██║   ██╔══██║██╔══██╗██╔══╝  ██╔══╝      ██║▄▄ ██║██║   ██║██╔══╝  ██╔══██╗  ╚██╔╝
//     ██║   ██║  ██║██║  ██║███████╗███████╗    ╚██████╔╝╚██████╔╝███████╗██║  ██║   ██║
//     ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝     ╚══▀▀═╝  ╚═════╝ ╚══════╝╚═╝  ╚═╝   ╚═╝
//

var util = require('util');
var _ = require('lodash');

module.exports = function forgeStageThreeQuery(options) {
  //  ╦  ╦╔═╗╦  ╦╔╦╗╔═╗╔╦╗╔═╗  ┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
  //  ╚╗╔╝╠═╣║  ║ ║║╠═╣ ║ ║╣   │ │├─┘ │ ││ ││││└─┐
  //   ╚╝ ╩ ╩╩═╝╩═╩╝╩ ╩ ╩ ╚═╝  └─┘┴   ┴ ┴└─┘┘└┘└─┘
  if (!_.has(options, 'stageTwoQuery') || !_.isPlainObject(options.stageTwoQuery)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `stageTwoQuery` option.');
  }

  if (!_.has(options, 'identity') || !_.isString(options.identity)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `identity` option.');
  }

  if (!_.has(options, 'schema') || !_.isPlainObject(options.schema)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `schema` option.');
  }

  if (!_.has(options, 'transformer') || !_.isObject(options.transformer)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `transformer` option.');
  }

  if (!_.has(options, 'originalModels') || !_.isPlainObject(options.originalModels)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `originalModels` option.');
  }


  // Store the options to prevent typing so much
  var stageTwoQuery = options.stageTwoQuery;
  var identity = options.identity;
  var transformer = options.transformer;
  var schema = options.schema;
  var originalModels = options.originalModels;


  //  ╔═╗╦╔╗╔╔╦╗  ┌┬┐┌─┐┌┬┐┌─┐┬
  //  ╠╣ ║║║║ ║║  ││││ │ ││├┤ │
  //  ╚  ╩╝╚╝═╩╝  ┴ ┴└─┘─┴┘└─┘┴─┘
  // Grab the current model definition from the schema. It will be used in all
  // sorts of ways.
  var model;
  try {
    model = schema[identity];
  } catch (e) {
    throw new Error('A model with the identity ' + identity + ' could not be found in the schema. Perhaps the wrong schema was used?');
  }


  //  ╔═╗╦╔╗╔╔╦╗  ┌─┐┬─┐┬┌┬┐┌─┐┬─┐┬ ┬  ┬┌─┌─┐┬ ┬
  //  ╠╣ ║║║║ ║║  ├─┘├┬┘││││├─┤├┬┘└┬┘  ├┴┐├┤ └┬┘
  //  ╚  ╩╝╚╝═╩╝  ┴  ┴└─┴┴ ┴┴ ┴┴└─ ┴   ┴ ┴└─┘ ┴
  // Get the current model's primary key attribute
  var modelPrimaryKey;
  _.each(model.attributes, function(val, key) {
    if (_.has(val, 'primaryKey')) {
      modelPrimaryKey = val.columnName || key;
    }
  });


  //  ╔╗ ╦ ╦╦╦  ╔╦╗   ┬┌─┐┬┌┐┌  ┬┌┐┌┌─┐┌┬┐┬─┐┬ ┬┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
  //  ╠╩╗║ ║║║   ║║   ││ │││││  ││││└─┐ │ ├┬┘│ ││   │ ││ ││││└─┐
  //  ╚═╝╚═╝╩╩═╝═╩╝  └┘└─┘┴┘└┘  ┴┘└┘└─┘ ┴ ┴└─└─┘└─┘ ┴ ┴└─┘┘└┘└─┘
  // Build the JOIN logic for the population
  var joins = [];
  _.each(stageTwoQuery.populates, function(populateCriteria, populateAttribute) {
    try {
      // Find the normalized schema value for the populated attribute
      var attribute = model.attributes[populateAttribute];
      if (!attribute) {
        throw new Error('In ' + util.format('`.populate("%s")`', populateAttribute) + ', attempting to populate an attribute that doesn\'t exist');
      }

      // Grab the key being populated from the original model definition to check
      // if it is a has many or belongs to. If it's a belongs_to the adapter needs
      // to know that it should replace the foreign key with the associated value.
      var parentKey = originalModels[identity].attributes[populateAttribute];

      // Build the initial join object that will link this collection to either another collection
      // or to a junction table.
      var join = {
        parent: identity,
        parentKey: attribute.columnName || modelPrimaryKey,
        child: attribute.references,
        childKey: attribute.on,
        alias: populateAttribute,
        removeParentKey: !!parentKey.model,
        model: !!_.has(parentKey, 'model'),
        collection: !!_.has(parentKey, 'collection')
      };

      // Build select object to use in the integrator
      var select = [];
      var customSelect = populateCriteria.select && _.isArray(populateCriteria.select);
      _.each(schema[attribute.references].attributes, function(val, key) {
        // Ignore virtual attributes
        if(_.has(val, 'collection')) {
          return;
        }

        // Check if the user has defined a custom select
        if(customSelect && !_.includes(populateCriteria.select, key)) {
          return;
        }

        if (!_.has(val, 'columnName')) {
          select.push(key);
          return;
        }

        select.push(val.columnName);
      });

      // Ensure the primary key and foreign key on the child are always selected.
      // otherwise things like the integrator won't work correctly
      var childPk;
      _.each(schema[attribute.references].attributes, function(val, key) {
        if(_.has(val, 'primaryKey') && val.primaryKey) {
          childPk = val.columnName || key;
        }
      });

      select.push(childPk);

      // Add the foreign key for collections so records can be turned into nested
      // objects.
      if (join.collection) {
        select.push(attribute.on);
      }

      // Make sure the join's select is unique
      join.select = _.uniq(select);

      // Find the schema of the model the attribute references
      var referencedSchema = schema[attribute.references];
      var reference = null;

      // If linking to a junction table, the attributes shouldn't be included in the return value
      if (referencedSchema.junctionTable) {
        join.select = false;
        reference = _.find(referencedSchema.attributes, function(referencedAttribute) {
          return referencedAttribute.references && referencedAttribute.columnName !== attribute.on;
        });
      }
      // If it's a through table, treat it the same way as a junction table for now
      else if (referencedSchema.throughTable && referencedSchema.throughTable[identity + '.' + populateAttribute]) {
        join.select = false;
        reference = referencedSchema.attributes[referencedSchema.throughTable[identity + '.' + populateAttribute]];
      }

      // Add the first join
      joins.push(join);

      // If a junction table is used ,add an additional join to get the data
      if (reference && _.has(attribute, 'on')) {
        var selects = [];
        _.each(schema[reference.references].attributes, function(val, key) {
          // Ignore virtual attributes
          if(_.has(val, 'collection')) {
            return;
          }

          // Check if the user has defined a custom select and if so normalize it
          if(customSelect && !_.includes(populateCriteria.select, key)) {
            return;
          }

          if (!_.has(val, 'columnName')) {
            selects.push(key);
            return;
          }

          selects.push(val.columnName);
        });

        // Ensure the primary key and foreign are always selected. Otherwise things like the
        // integrator won't work correctly
        _.each(schema[reference.references].attributes, function(val, key) {
          if(_.has(val, 'primaryKey') && val.primaryKey) {
            childPk = val.columnName || key;
          }
        });

        selects.push(childPk);

        join = {
          parent: attribute.references,
          parentKey: reference.columnName,
          child: reference.references,
          childKey: reference.on,
          select: _.uniq(selects),
          alias: populateAttribute,
          junctionTable: true,
          removeParentKey: !!parentKey.model,
          model: false,
          collection: true<commit_msg>only normalize select column names once<commit_after>//  ███████╗ ██████╗ ██████╗  ██████╗ ███████╗    ███████╗████████╗ █████╗  ██████╗ ███████╗
//  ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝    ██╔════╝╚══██╔══╝██╔══██╗██╔════╝ ██╔════╝
//  █████╗  ██║   ██║██████╔╝██║  ███╗█████╗      ███████╗   ██║   ███████║██║  ███╗█████╗
//  ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝      ╚════██║   ██║   ██╔══██║██║   ██║██╔══╝
//  ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗    ███████║   ██║   ██║  ██║╚██████╔╝███████╗
//  ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝    ╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//
//  ████████╗██╗  ██╗██████╗ ███████╗███████╗     ██████╗ ██╗   ██╗███████╗██████╗ ██╗   ██╗
//  ╚══██╔══╝██║  ██║██╔══██╗██╔════╝██╔════╝    ██╔═══██╗██║   ██║██╔════╝██╔══██╗╚██╗ ██╔╝
//     ██║   ███████║██████╔╝█████╗  █████╗      ██║   ██║██║   ██║█████╗  ██████╔╝ ╚████╔╝
//     ██║   ██╔══██║██╔══██╗██╔══╝  ██╔══╝      ██║▄▄ ██║██║   ██║██╔══╝  ██╔══██╗  ╚██╔╝
//     ██║   ██║  ██║██║  ██║███████╗███████╗    ╚██████╔╝╚██████╔╝███████╗██║  ██║   ██║
//     ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝     ╚══▀▀═╝  ╚═════╝ ╚══════╝╚═╝  ╚═╝   ╚═╝
//

var util = require('util');
var _ = require('lodash');

module.exports = function forgeStageThreeQuery(options) {
  //  ╦  ╦╔═╗╦  ╦╔╦╗╔═╗╔╦╗╔═╗  ┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
  //  ╚╗╔╝╠═╣║  ║ ║║╠═╣ ║ ║╣   │ │├─┘ │ ││ ││││└─┐
  //   ╚╝ ╩ ╩╩═╝╩═╩╝╩ ╩ ╩ ╚═╝  └─┘┴   ┴ ┴└─┘┘└┘└─┘
  if (!_.has(options, 'stageTwoQuery') || !_.isPlainObject(options.stageTwoQuery)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `stageTwoQuery` option.');
  }

  if (!_.has(options, 'identity') || !_.isString(options.identity)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `identity` option.');
  }

  if (!_.has(options, 'schema') || !_.isPlainObject(options.schema)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `schema` option.');
  }

  if (!_.has(options, 'transformer') || !_.isObject(options.transformer)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `transformer` option.');
  }

  if (!_.has(options, 'originalModels') || !_.isPlainObject(options.originalModels)) {
    throw new Error('Invalid options passed to `.buildStageThreeQuery()`. Missing or invalud `originalModels` option.');
  }


  // Store the options to prevent typing so much
  var stageTwoQuery = options.stageTwoQuery;
  var identity = options.identity;
  var transformer = options.transformer;
  var schema = options.schema;
  var originalModels = options.originalModels;


  //  ╔═╗╦╔╗╔╔╦╗  ┌┬┐┌─┐┌┬┐┌─┐┬
  //  ╠╣ ║║║║ ║║  ││││ │ ││├┤ │
  //  ╚  ╩╝╚╝═╩╝  ┴ ┴└─┘─┴┘└─┘┴─┘
  // Grab the current model definition from the schema. It will be used in all
  // sorts of ways.
  var model;
  try {
    model = schema[identity];
  } catch (e) {
    throw new Error('A model with the identity ' + identity + ' could not be found in the schema. Perhaps the wrong schema was used?');
  }


  //  ╔═╗╦╔╗╔╔╦╗  ┌─┐┬─┐┬┌┬┐┌─┐┬─┐┬ ┬  ┬┌─┌─┐┬ ┬
  //  ╠╣ ║║║║ ║║  ├─┘├┬┘││││├─┤├┬┘└┬┘  ├┴┐├┤ └┬┘
  //  ╚  ╩╝╚╝═╩╝  ┴  ┴└─┴┴ ┴┴ ┴┴└─ ┴   ┴ ┴└─┘ ┴
  // Get the current model's primary key attribute
  var modelPrimaryKey;
  _.each(model.attributes, function(val, key) {
    if (_.has(val, 'primaryKey')) {
      modelPrimaryKey = val.columnName || key;
    }
  });


  //  ╔╗ ╦ ╦╦╦  ╔╦╗   ┬┌─┐┬┌┐┌  ┬┌┐┌┌─┐┌┬┐┬─┐┬ ┬┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
  //  ╠╩╗║ ║║║   ║║   ││ │││││  ││││└─┐ │ ├┬┘│ ││   │ ││ ││││└─┐
  //  ╚═╝╚═╝╩╩═╝═╩╝  └┘└─┘┴┘└┘  ┴┘└┘└─┘ ┴ ┴└─└─┘└─┘ ┴ ┴└─┘┘└┘└─┘
  // Build the JOIN logic for the population
  var joins = [];
  _.each(stageTwoQuery.populates, function(populateCriteria, populateAttribute) {
    try {
      // Find the normalized schema value for the populated attribute
      var attribute = model.attributes[populateAttribute];
      if (!attribute) {
        throw new Error('In ' + util.format('`.populate("%s")`', populateAttribute) + ', attempting to populate an attribute that doesn\'t exist');
      }

      // Grab the key being populated from the original model definition to check
      // if it is a has many or belongs to. If it's a belongs_to the adapter needs
      // to know that it should replace the foreign key with the associated value.
      var parentKey = originalModels[identity].attributes[populateAttribute];

      // Build the initial join object that will link this collection to either another collection
      // or to a junction table.
      var join = {
        parent: identity,
        parentKey: attribute.columnName || modelPrimaryKey,
        child: attribute.references,
        childKey: attribute.on,
        alias: populateAttribute,
        removeParentKey: !!parentKey.model,
        model: !!_.has(parentKey, 'model'),
        collection: !!_.has(parentKey, 'collection')
      };

      // Build select object to use in the integrator
      var select = [];
      var customSelect = populateCriteria.select && _.isArray(populateCriteria.select);
      _.each(schema[attribute.references].attributes, function(val, key) {
        // Ignore virtual attributes
        if(_.has(val, 'collection')) {
          return;
        }

        // Check if the user has defined a custom select
        if(customSelect && !_.includes(populateCriteria.select, key)) {
          return;
        }

        // Add the key to the select
        select.push(key);
      });

      // Ensure the primary key and foreign key on the child are always selected.
      // otherwise things like the integrator won't work correctly
      var childPk;
      _.each(schema[attribute.references].attributes, function(val, key) {
        if(_.has(val, 'primaryKey') && val.primaryKey) {
          childPk = key;
        }
      });

      select.push(childPk);

      // Add the foreign key for collections so records can be turned into nested
      // objects.
      if (join.collection) {
        select.push(attribute.on);
      }

      // Make sure the join's select is unique
      join.select = _.uniq(select);

      // Find the schema of the model the attribute references
      var referencedSchema = schema[attribute.references];
      var reference = null;

      // If linking to a junction table, the attributes shouldn't be included in the return value
      if (referencedSchema.junctionTable) {
        join.select = false;
        reference = _.find(referencedSchema.attributes, function(referencedAttribute) {
          return referencedAttribute.references && referencedAttribute.columnName !== attribute.on;
        });
      }
      // If it's a through table, treat it the same way as a junction table for now
      else if (referencedSchema.throughTable && referencedSchema.throughTable[identity + '.' + populateAttribute]) {
        join.select = false;
        reference = referencedSchema.attributes[referencedSchema.throughTable[identity + '.' + populateAttribute]];
      }

      // Add the first join
      joins.push(join);

      // If a junction table is used ,add an additional join to get the data
      if (reference && _.has(attribute, 'on')) {
        var selects = [];
        _.each(schema[reference.references].attributes, function(val, key) {
          // Ignore virtual attributes
          if(_.has(val, 'collection')) {
            return;
          }

          // Check if the user has defined a custom select and if so normalize it
          if(customSelect && !_.includes(populateCriteria.select, key)) {
            return;
          }

          // Add the value to the select
          selects.push(key);
        });

        // Ensure the primary key and foreign are always selected. Otherwise things like the
        // integrator won't work correctly
        _.each(schema[reference.references].attributes, function(val, key) {
          if(_.has(val, 'primaryKey') && val.primaryKey) {
            childPk = val.columnName || key;
          }
        });

        selects.push(childPk);

        join = {
          parent: attribute.references,
          parentKey: reference.columnName,
          child: reference.references,
          childKey: reference.on,
          select: _.uniq(selects),
          alias: populateAttribute,
          junctionTable: true,
          removeParentKey: !!parentKey.model,
          model: false,
          collection: true
{'fraction_non_alphanumeric': 0.2365559800176315, 'fraction_numerical': 0.0, 'mean_word_length': 2.621195999148755, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '969711', 'n_tokens_mistral': 6607, 'n_tokens_neox': 6909, 'n_words': 1503}