<commit_before>/**
 * Module dependencies
 */

var util = require('util');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');
var rttc = require('rttc');
var getModel = require('../../ontology/get-model');
var getAttribute = require('../../ontology/get-attribute');


/**
 * normalizeComparisonValue()
 *
 * Validate and normalize the provided value vs. a particular attribute,
 * taking `type` into account, as well as whether the referenced attribute is
 * a singular association or a primary key. And if no such attribute exists,
 * then this at least ensure the value is JSON-compatible.
 * ------------------------------------------------------------------------------------------
 * This utility is for the purposes of `normalizeConstraint()` (e.g. within `where` clause)
 * so does not care about required/defaultsTo/etc.  It is used for eq constraints, `in` and
 * `nin` modifiers, as well as comparison modifiers like `!=`, `<`, `>`, `<=`, and `>=`.
 *
 * > • It always tolerates `null` (& does not care about required/defaultsTo/etc.)
 * > • Collection attrs are never allowed.
 * >   (Attempting to use one will cause this to throw a consistency violation error
 * >    so i.e. it should be checked beforehand.)
 * ------------------------------------------------------------------------------------------
 * @param  {Ref} value
 *         The eq constraint or modifier to normalize.
 *         > MAY BE MUTATED IN-PLACE!!  (but not necessarily)
 *
 * @param {String} attrName
 *        The name of the attribute to check against.
 *
 * @param {String} modelIdentity
 *        The identity of the model the attribute belongs to (e.g. "pet" or "user")
 *
 * @param {Ref} orm
 *        The Waterline ORM instance.
 * ------------------------------------------------------------------------------------------
 * @returns {Ref}
 *          The provided value, now normalized and guaranteed to match the specified attribute.
 *          This might be the same original reference, or it might not.
 * ------------------------------------------------------------------------------------------
 * @throws {Error} if invalid and cannot be coerced
 *         @property {String} code (=== "E_VALUE_NOT_USABLE")
 * ------------------------------------------------------------------------------------------
 * @throws {Error} If anything unexpected happens, e.g. bad usage, or a failed assertion.
 * ------------------------------------------------------------------------------------------
 */

module.exports = function normalizeComparisonValue (value, attrName, modelIdentity, orm){
  if (_.isUndefined(value)) { throw new Error('Consistency violation: This internal utility must always be called with a first argument (the value to normalize).  But instead, got: '+util.inspect(value, {depth:5})+''); }
  if (!_.isString(attrName)) { throw new Error('Consistency violation: This internal utility must always be called with a valid second argument (the attribute name).  But instead, got: '+util.inspect(attrName, {depth:5})+''); }
  if (!_.isString(modelIdentity)) { throw new Error('Consistency violation: This internal utility must always be called with a valid third argument (the model identity).  But instead, got: '+util.inspect(modelIdentity, {depth:5})+''); }
  if (!_.isObject(orm)) { throw new Error('Consistency violation: This internal utility must always be called with a valid fourth argument (the orm instance).  But instead, got: '+util.inspect(orm, {depth:5})+''); }


  // - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -
  // FUTURE: Maybe make the RTTC validation in this file strict (instead of also performing light coercion).
  // On one hand, it's better to show an error than have experience of fetching stuff from the database
  // be inconsistent with what you can search for.  But on the other hand, it's nice to have Waterline
  // automatically coerce the string "4" into the number 4 (and vice versa) within an eq constraint.
  // - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -


  // Look up the primary Waterline model and attribute.
  var WLModel = getModel(modelIdentity, orm);

  // Try to look up the attribute definition.
  // (`attrDef` will either be a valid attribute or `undefined`)
  var attrDef = WLModel.attributes[attrName];

  // If this attribute exists, ensure that it is not a plural association.
  if (attrDef) {
    assert(!attrDef.collection, 'Should not call this internal utility on a plural association (i.e. `collection` attribute).');
  }

<commit_msg>replace assertion with friendlier error (when explicitly trying to use `undefined` on the RHS of most modifiers in a complex constraint within a `where` clause<commit_after>/**
 * Module dependencies
 */

var util = require('util');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');
var rttc = require('rttc');
var getModel = require('../../ontology/get-model');
var getAttribute = require('../../ontology/get-attribute');


/**
 * normalizeComparisonValue()
 *
 * Validate and normalize the provided value vs. a particular attribute,
 * taking `type` into account, as well as whether the referenced attribute is
 * a singular association or a primary key. And if no such attribute exists,
 * then this at least ensure the value is JSON-compatible.
 * ------------------------------------------------------------------------------------------
 * This utility is for the purposes of `normalizeConstraint()` (e.g. within `where` clause)
 * so does not care about required/defaultsTo/etc.  It is used for eq constraints, `in` and
 * `nin` modifiers, as well as comparison modifiers like `!=`, `<`, `>`, `<=`, and `>=`.
 *
 * > • It always tolerates `null` (& does not care about required/defaultsTo/etc.)
 * > • Collection attrs are never allowed.
 * >   (Attempting to use one will cause this to throw a consistency violation error
 * >    so i.e. it should be checked beforehand.)
 * ------------------------------------------------------------------------------------------
 * @param  {Ref} value
 *         The eq constraint or modifier to normalize.
 *         > MAY BE MUTATED IN-PLACE!!  (but not necessarily)
 *
 * @param {String} attrName
 *        The name of the attribute to check against.
 *
 * @param {String} modelIdentity
 *        The identity of the model the attribute belongs to (e.g. "pet" or "user")
 *
 * @param {Ref} orm
 *        The Waterline ORM instance.
 * ------------------------------------------------------------------------------------------
 * @returns {Ref}
 *          The provided value, now normalized and guaranteed to match the specified attribute.
 *          This might be the same original reference, or it might not.
 * ------------------------------------------------------------------------------------------
 * @throws {Error} if invalid and cannot be coerced
 *         @property {String} code (=== "E_VALUE_NOT_USABLE")
 * ------------------------------------------------------------------------------------------
 * @throws {Error} If anything unexpected happens, e.g. bad usage, or a failed assertion.
 * ------------------------------------------------------------------------------------------
 */

module.exports = function normalizeComparisonValue (value, attrName, modelIdentity, orm){
  if (!_.isString(attrName)) { throw new Error('Consistency violation: This internal utility must always be called with a valid second argument (the attribute name).  But instead, got: '+util.inspect(attrName, {depth:5})+''); }
  if (!_.isString(modelIdentity)) { throw new Error('Consistency violation: This internal utility must always be called with a valid third argument (the model identity).  But instead, got: '+util.inspect(modelIdentity, {depth:5})+''); }
  if (!_.isObject(orm)) { throw new Error('Consistency violation: This internal utility must always be called with a valid fourth argument (the orm instance).  But instead, got: '+util.inspect(orm, {depth:5})+''); }


  
  if (_.isUndefined(modifier)) {
    throw flaverr('E_VALUE_NOT_USABLE', new Error(
      'Cannot compare vs. `undefined`!\n'+
      '--\n'+
      'Usually, this just means there is some kind of logic error in the code that builds this `where` clause.  '+
      'On the other hand, if you purposely built this query with `undefined`, bear in mind that you\'ll '+
      'need to be more explicit:  When comparing "emptiness" in a `where` clause, specify null, empty string (''), '+
      '0, or false.\n'+
      '--'
    ));
  }//-•
  
  // - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -
  // FUTURE: Maybe make the RTTC validation in this file strict (instead of also performing light coercion).
  // On one hand, it's better to show an error than have experience of fetching stuff from the database
  // be inconsistent with what you can search for.  But on the other hand, it's nice to have Waterline
  // automatically coerce the string "4" into the number 4 (and vice versa) within an eq constraint.
  // - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -


  // Look up the primary Waterline model and attribute.
  var WLModel = getModel(modelIdentity, orm);

  // Try to look up the attribute definition.
  // (`attrDef` will either be a valid attribute or `undefined`)
  var attrDef = WLModel.attributes[attrName];

  // If this attribute exists, ensure that it is not a plural association.
  if (attrDef) {
    assert(!attrDef.collection, 'Should not call this internal utility on a plural association (i.e. `collection` attribute).');
  }


{'fraction_non_alphanumeric': 0.22372050260496476, 'fraction_numerical': 0.001225865767698437, 'mean_word_length': 1.990226023213195, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, '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': '2275448', 'n_tokens_mistral': 2564, 'n_tokens_neox': 2490, 'n_words': 1024}