<commit_before>'use strict';

var Utils = require('./../utils')
  , Helpers = require('./helpers')
  , _ = require('lodash')
  , Association = require('./base')
  , Transaction = require('../transaction')
  , Model = require('../model')
  , CounterCache = require('../plugins/counter-cache');

var HasManySingleLinked = require('./has-many-single-linked')
  , HasManyDoubleLinked = require('./has-many-double-linked');

module.exports = (function() {
  var HasMany = function(source, target, options) {
    Association.call(this);
    var self = this;

    this.associationType = 'HasMany';
    this.source = source;
    this.target = target;
    this.targetAssociation = null;
    this.options = options || {};
    this.sequelize = source.daoFactoryManager.sequelize;
    this.through = options.through;
    this.scope = options.scope;
    this.isMultiAssociation = true;
    this.isSelfAssociation = this.source === this.target;
    this.doubleLinked = false;
    this.as = this.options.as;
    this.combinedTableName = Utils.combineTableNames(
      this.source.tableName,
      this.isSelfAssociation ? (this.as || this.target.tableName) : this.target.tableName
    );

    if (Utils._.isObject(this.options.foreignKey)) {
      this.foreignKeyAttribute = this.options.foreignKey;
      this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName;
    } else {
      this.foreignKeyAttribute = {};
      this.foreignKey = this.options.foreignKey;
    }

    /*
     * Map joinTableModel/Name to through for BC
     */
    if (this.through === undefined) {
      this.through = this.options.joinTableModel || this.options.joinTableName;

      /*
       * If both are undefined, see if useJunctionTable was false (for self associations) - else assume through to be true
       */
      if (this.through === undefined) {
        if (this.options.useJunctionTable === false) {
          this.through = null;
        } else {
          this.through = true;
        }
      }
    }

    if (this.through !== null && !this.through.model) {
      this.through = {
        model: this.through
      };
    }

    /*
     * Determine associationAccessor, especially for include options to identify the correct model
     */

    this.associationAccessor = this.as;
    if (!this.associationAccessor) {
      if (typeof this.through.model === 'string') {
        this.associationAccessor = this.through.model;
      } else if (Object(this.through.model) === this.through.model) {
        this.associationAccessor = this.through.model.tableName;
      } else {
        this.associationAccessor = this.combinedTableName;
      }
    }

    /*
     * If self association, this is the target association - Unless we find a pairing association
     */
    if (this.isSelfAssociation) {
      // check 'as' is defined for many-to-many self-association
      if (this.through && this.through.model !== true && !this.as) {
        throw new Error('\'as\' must be defined for many-to-many self-associations');
      }

      this.targetAssociation = this;
    }

    /*
     * Else find partner DAOFactory if present, to identify double linked association
     */
    if (this.through) {
      _.each(this.target.associations, function(association, accessor) {
        if (self.source === association.target && association.associationType === 'HasMany') {
          var paired;

          // If through is default, we determine pairing by the accesor value (i.e. DAOFactory's using as won't pair, but regular ones will)
          if (self.through.model === true) {
            paired = accessor === self.associationAccessor;
          }
          // If through is not default, determine pairing by through value (model/string)
          else {
            paired = self.options.through === association.options.through ||
                     self.options.through === (association.options.through && association.options.through.model) ||
                     (self.options.through && self.options.through.model) === (association.options.through && association.options.through.model) ||
                     (self.options.through && self.options.through.model) === association.options.through;
          }
          // If paired, set properties identifying both associations as double linked, and allow them to each eachtoerh
          if (paired) {
            self.doubleLinked = true;
            association.doubleLinked = true;

            self.targetAssociation = association;
            association.targetAssociation = self;
          }
        }
      });
    }

    /*
     * If we are double linked, and through is either default or a string, we create the through model and set it on both associations
     */
    if (this.doubleLinked && this.through.model === true) {
      this.through.model = this.combinedTableName;
    }

    if (typeof this.through.model === 'string') {
      var defineOptions = _.extend(this.options, {
        tableName: this.through.model,
        paranoid: false  // A paranoid join table does not make sense
      });
      //we dont want indexes here
      delete defineOptions.indexes;
      console.log(defineOptions);
      this.through.model = this.sequelize.define(this.through.model, {}, defineOptions);

      if (this.targetAssociation) {
        this.targetAssociation.through.model = this.through.model;
      }
    }<commit_msg>possible fix for #2416 by dropping indexes from the creation of many-to-many relation tables<commit_after>'use strict';

var Utils = require('./../utils')
  , Helpers = require('./helpers')
  , _ = require('lodash')
  , Association = require('./base')
  , Transaction = require('../transaction')
  , Model = require('../model')
  , CounterCache = require('../plugins/counter-cache');

var HasManySingleLinked = require('./has-many-single-linked')
  , HasManyDoubleLinked = require('./has-many-double-linked');

module.exports = (function() {
  var HasMany = function(source, target, options) {
    Association.call(this);
    var self = this;

    this.associationType = 'HasMany';
    this.source = source;
    this.target = target;
    this.targetAssociation = null;
    this.options = options || {};
    this.sequelize = source.daoFactoryManager.sequelize;
    this.through = options.through;
    this.scope = options.scope;
    this.isMultiAssociation = true;
    this.isSelfAssociation = this.source === this.target;
    this.doubleLinked = false;
    this.as = this.options.as;
    this.combinedTableName = Utils.combineTableNames(
      this.source.tableName,
      this.isSelfAssociation ? (this.as || this.target.tableName) : this.target.tableName
    );

    if (Utils._.isObject(this.options.foreignKey)) {
      this.foreignKeyAttribute = this.options.foreignKey;
      this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName;
    } else {
      this.foreignKeyAttribute = {};
      this.foreignKey = this.options.foreignKey;
    }

    /*
     * Map joinTableModel/Name to through for BC
     */
    if (this.through === undefined) {
      this.through = this.options.joinTableModel || this.options.joinTableName;

      /*
       * If both are undefined, see if useJunctionTable was false (for self associations) - else assume through to be true
       */
      if (this.through === undefined) {
        if (this.options.useJunctionTable === false) {
          this.through = null;
        } else {
          this.through = true;
        }
      }
    }

    if (this.through !== null && !this.through.model) {
      this.through = {
        model: this.through
      };
    }

    /*
     * Determine associationAccessor, especially for include options to identify the correct model
     */

    this.associationAccessor = this.as;
    if (!this.associationAccessor) {
      if (typeof this.through.model === 'string') {
        this.associationAccessor = this.through.model;
      } else if (Object(this.through.model) === this.through.model) {
        this.associationAccessor = this.through.model.tableName;
      } else {
        this.associationAccessor = this.combinedTableName;
      }
    }

    /*
     * If self association, this is the target association - Unless we find a pairing association
     */
    if (this.isSelfAssociation) {
      // check 'as' is defined for many-to-many self-association
      if (this.through && this.through.model !== true && !this.as) {
        throw new Error('\'as\' must be defined for many-to-many self-associations');
      }

      this.targetAssociation = this;
    }

    /*
     * Else find partner DAOFactory if present, to identify double linked association
     */
    if (this.through) {
      _.each(this.target.associations, function(association, accessor) {
        if (self.source === association.target && association.associationType === 'HasMany') {
          var paired;

          // If through is default, we determine pairing by the accesor value (i.e. DAOFactory's using as won't pair, but regular ones will)
          if (self.through.model === true) {
            paired = accessor === self.associationAccessor;
          }
          // If through is not default, determine pairing by through value (model/string)
          else {
            paired = self.options.through === association.options.through ||
                     self.options.through === (association.options.through && association.options.through.model) ||
                     (self.options.through && self.options.through.model) === (association.options.through && association.options.through.model) ||
                     (self.options.through && self.options.through.model) === association.options.through;
          }
          // If paired, set properties identifying both associations as double linked, and allow them to each eachtoerh
          if (paired) {
            self.doubleLinked = true;
            association.doubleLinked = true;

            self.targetAssociation = association;
            association.targetAssociation = self;
          }
        }
      });
    }

    /*
     * If we are double linked, and through is either default or a string, we create the through model and set it on both associations
     */
    if (this.doubleLinked && this.through.model === true) {
      this.through.model = this.combinedTableName;
    }

    if (typeof this.through.model === 'string') {
      this.through.model = this.sequelize.define(this.through.model, {}, _.extend(this.options, {
        tableName: this.through.model,
        indexes: {}, //we dont want indexes here (as referenced in #2416)
        paranoid: false  // A paranoid join table does not make sense
      }));

      if (this.targetAssociation) {
        this.targetAssociation.through.model = this.through.model;
      }
    }
{'fraction_non_alphanumeric': 0.11971830985915492, 'fraction_numerical': 0.0007412898443291327, 'mean_word_length': 2.482736366569861, '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': '3838998', 'n_tokens_mistral': 3001, 'n_tokens_neox': 2894, 'n_words': 726}