<commit_before>'use strict';

var Utils = require('../../utils')
  , SqlString = require('../../sql-string')
  , DataTypes = require('./data-types')
  , _ = require('lodash')
  , _options
  , _dialect = 'mssql'
  , _sequelize;

/*
  Escape a value (e.g. a string, number or date)
*/
var attributeMap = {
  notNull:"NOT NULL",
  allowNull:"NULL",
  autoIncrement:"IDENTITY(1,1)",
  defaultValue:"DEFAULT",
  unique:"UNIQUE",
  primaryKey:"PRIMARY KEY",
  foreignKey:"FOREIGN KEY",
  comment:"COMMENT",
  references:"REFERENCES",
  onDelete:"ON DELETE",
  onUpdate:"ON UPDATE",
  default:"DEFAULT"
};

function escape(value, field) {
  if (value && value._isSequelizeMethod) {
    return value.toString();
  } else {
    return SqlString.escape(value, false, _options.timezone, _dialect, field);
  }
}

function quoteIdentifier(identifier, force) {
  if (identifier === '*') return identifier;
  return Utils.addTicks(identifier, '"');
}

/*
  Split an identifier into .-separated tokens and quote each part
*/
function quoteIdentifiers(identifiers, force) {
  if (identifiers.indexOf('.') !== -1) {
    identifiers = identifiers.split('.');
    return quoteIdentifier(identifiers.slice(0, identifiers.length - 1).join('.'))
      + '.' + quoteIdentifier(identifiers[identifiers.length - 1]);
  } else {
    return quoteIdentifier(identifiers);
  }
}

function wrapSingleQuote(identifier){
  return Utils.addTicks(identifier, "'");
}

function nameIndexes(indexes, rawTablename) {
  return Utils._.map(indexes, function (index) {
    if (!index.hasOwnProperty('name')) {
      var onlyAttributeNames = index.fields.map(function(attribute) {
        return (typeof attribute === 'string') ? attribute : attribute.attribute;
      }.bind(this));

      index.name = Utils.inflection.underscore(rawTablename + '_' + onlyAttributeNames.join('_'));
    }

    return index;
  });
}

function fieldsToSql(fields, singleQuote){
  var fieldStr = [];
  for (var key in fields) {
    if (fields.hasOwnProperty(key)) {
      if(singleQuote){
        fieldStr.push(wrapSingleQuote(key));
      }else{
        fieldStr.push(quoteIdentifier(key));
      }
    }
  }
  if(fieldStr){
    if(fieldStr.length > 0){
      return fieldStr.join(',');
    }
  }
  return '';
}

function processValue(val, modelAttribute){
  var sql;
  if(val instanceof Utils.cast){
    sql = 'CAST(';
    if(val.val._isSequelizeMethod){
      sql += processValue(val.val, modelAttribute) + ' AS ' + val.type.toUpperCase();
    }else{
      sql += escape(val.val) + ' AS ' + val.type.toUpperCase();
    }
    return sql + ')';
  } else if(val instanceof Utils.literal){
    return val.val;
  } else if (val instanceof Utils.fn) {
    sql = val.fn + '(' + val.args.map(function(arg) {
      if (arg._isSequelizeMethod) {
        return processValue(arg, modelAttribute);
      } else{
        return escape(arg);
      }
    }).join(', ') + ')';
    return sql;
  } else if (val === true || val === false){
    return wrapSingleQuote(val.toString());
  } else if (val instanceof Utils.col) {
    if (Array.isArray(val.col)) {
      if (!modelAttribute) {
        throw new Error('Cannot call Sequelize.col() with array outside of order / group clause');
      }
    } else if (val.col.indexOf('*') === 0) {
      return '*';
    }
    return quoteIdentifier(val.col);
  } else{
    return escape(val, modelAttribute);
  }
}

function valuesToSql(fields, modelAttributeMap, isUpdate){
  var values = [];
  for (var key in fields) {
    if (fields.hasOwnProperty(key)) {
      if(isUpdate){
        values.push(quoteIdentifier(key) + '=' + processValue(fields[key], (modelAttributeMap && modelAttributeMap[key]) || undefined));
      } else {
        values.push(processValue(fields[key], (modelAttributeMap && modelAttributeMap[key]) || undefined));
      }
    }
  }
  if(values){
    if(values.length > 0){
      return values.join(',');
    }
  }
  return '';
}

function loadColumn(attributes){
  var attrStr = [];
  for (var attr in attributes) {
    var dataType = attributes[attr];
    attrStr.push(quoteIdentifier(dataType));
  }
  return attrStr;
}

function addTableExistsWrapper(query, exists){
  return [
    "IF (",
      (exists ? "" : "NOT"), " EXISTS (",
      "SELECT * FROM INFORMATION_SCHEMA.TABLES",
      "WHERE TABLE_NAME='<%= unquotedTable %>'))",
    "BEGIN",
      query,
    "END"
  ].join(" ");
}

//select stuff
function loadFields(attributes){
  var attrStr = [];
  for (var attr in attributes) {
    attrStr.push(quoteIdentifier(attr));
  }
  return attrStr;
}

function processField(attribute, tableName){
  var sql = '';
  if(tableName){
    sql += quoteIdentifier(tableName) + '.';
  }
  if(attribute[0] !== attribute[1]){
    return sql + quoteIdentifier(attribute[0]) + ' AS ' + quoteIdentifier(attribute[1]);
   }else{
    return sql + quoteIdentifier(attribute[0]);
  }
}

function loadFieldsWithName(attributes, tableName){
  var attrStr = [];
  if(Array.isArray(attributes[0])){
    for (var i = 0; i < attributes.length; i++) {
      attrStr.push(processField(attributes[i], tableName));
    }
  }else{
    for (var attr in attributes) {
      if(tableName){
        attrStr.push(quoteIdentifier(tableName) + "." + quoteIdentifier(attr));
      }else{
        attrStr.push(quoteIdentifier(attr));
      }
    }
  }
  return attrStr.join(',');
}

function joinFields(attributes, tableName){
  var attrStr = [];
  if(tableName){
    for (var attr in attributes) {
      attrStr.push(quoteIdentifier(tableName)
        + "."
        + quoteIdentifier(attr)
        + " AS " + quoteIdentifier(tableName + "." + attr));
    }
  }
  return attrStr.join(',');
}

module.exports = {
  get options(){
    return _options;
  },

  set options(opt) {
    _options = opt;
  },

  get dialect(){
    return _dialect;
  },

  set dialect(dial) {
    _dialect = dial;
  },

  get sequelize(){
    return _sequelize;
  },

  set sequelize(seq) {
    _sequelize = seq;
  },

  quoteIdentifier: function(val){
    return quoteIdentifier(val);
  },

  quoteIdentifiers: function(val, force){
    return quoteIdentifiers(val, force);
  },

  escape: function(value, field) {
    return escape(value,field);
  },

  showTableSql: function(){
    return 'SELECT name FROM sys.Tables;';
  },

  processValue: function(val, modelAttribute){
    return processValue(val, modelAttribute);
  },

  quoteTable: function(param, as) {
    var table = '';
    if (as === true) {
      as = param.as || param.name || param;
    }

    if (_.isObject(param)) {
      if (param.schema) {
        table += param.schema + (param.delimiter || '.');
      }
      table += param.tableName;
      table = quoteIdentifier(table);
    } else {
      table = quoteIdentifier(param);
    }

    if (as) {
      table += ' AS ' + quoteIdentifier(as);
    }
    return table;
  },

  identityInsertWrapper: function(query, table){
    return[
      'SET IDENTITY_INSERT', quoteIdentifier(table), 'ON;',
      query,
      'SET IDENTITY_INSERT', quoteIdentifier(table), 'OFF;',
    ].join(' ');
  },

  getCreateSchemaSql: function(schema){
    return [
      'IF NOT EXISTS (SELECT schema_name',
      'FROM information_schema.schemata',
      'WHERE schema_name = ', wrapSingleQuote(schema), ')',
      'BEGIN',
        'EXEC sp_executesql N\'CREATE SCHEMA', quoteIdentifier(schema),';\'',
      "END;"].join(' ');
  },

  getCreateTableSql: function(tableName, attributes, options) {
    var query = "CREATE TABLE <%= tableName %> (<%= attributes%>)";
    var attrStr     = []
      , self        = this
      , primaryKeys = Utils._.keys(Utils._.pick(attributes, function(dataType){
        return dataType.indexOf('PRIMARY KEY') >= 0;
      }));

    for (var attr in attributes) {
      var dataType = attributes[attr];
      attrStr.push(quoteIdentifier(attr) + " " + dataType);
    }
    var values = {
      unquotedTable: tableName,
      tableName: quoteIdentifier(tableName.toString()),
      attributes: attrStr.join(", ")
    };
    query = addTableExistsWrapper(query);
    return Utils._.template(query)(values).trim() + ";";
  },

  alterTableSql: function(tableName){
    var query = 'ALTER TABLE <%= tableName %>';
    var value = {
      tableName : quoteIdentifier(tableName)
    };
    return Utils._.template(query)(value);
  },

  dropTableSql: function(tableName, options){
    var query = "DROP TABLE <%= tableName %>";
    var values ={};
    values = {
      unquotedTable: tableName,
      tableName: quoteIdentifier(tableName.toString())
    };

    query = addTableExistsWrapper(query, true);
    return Utils._.template(query)(values).trim() + ";";
  },

  insertSql: function(tableName, valueHash, modelAttributeMap) {
    var query
      , valueQuery = 'INSERT INTO <%= tableName %> (<%= attributes %>)'
      , emptyQuery = 'INSERT INTO <%= tableName %>';

    valueQuery += ' OUTPUT <%= selFields %>  VALUES (<%= values %>)';
    if(modelAttributeMap){
      emptyQuery += ' OUTPUT <%= selFields %>';
    }
    emptyQuery += ' DEFAULT VALUES';

    valueHash = Utils.removeNullValuesFromHash(valueHash, _options.omitNull);

    var selFields = [];
    var insertKey = false;
    for (var key in modelAttributeMap) {
      selFields.push('INSERTED.' + quoteIdentifier( (modelAttributeMap[key].field || key)));
      if(modelAttributeMap[key].autoIncrement
        && (valueHash[key] === 'DEFAULT'
          || valueHash[key] === null)){
        delete valueHash[key];
      }else if(valueHash[key]
        && modelAttributeMap[key].autoIncrement){
        insertKey = true;
      }
    }

    var replacements = {
      tableName: quoteIdentifier(tableName.toString()),
      attributes: fieldsToSql(valueHash, false),
      selFields: selFields.join(','),
      values: valuesToSql(valueHash, modelAttributeMap)
    };

    query = (replacements.attributes.length ? valueQuery : emptyQuery) + ';';

    if(insertKey){
      query = this.identityInsertWrapper(query, tableName);
    }
    return Utils._.template(query)(replacements);
  },

  updateSql: function(tableName, valueHash, where, options, attributes){
    options = options || {};<commit_msg>fix virtual attributes in insert and update statements<commit_after>'use strict';

var Utils = require('../../utils')
  , SqlString = require('../../sql-string')
  , DataTypes = require('./data-types')
  , _ = require('lodash')
  , _options
  , _dialect = 'mssql'
  , _sequelize;

/*
  Escape a value (e.g. a string, number or date)
*/
var attributeMap = {
  notNull:"NOT NULL",
  allowNull:"NULL",
  autoIncrement:"IDENTITY(1,1)",
  defaultValue:"DEFAULT",
  unique:"UNIQUE",
  primaryKey:"PRIMARY KEY",
  foreignKey:"FOREIGN KEY",
  comment:"COMMENT",
  references:"REFERENCES",
  onDelete:"ON DELETE",
  onUpdate:"ON UPDATE",
  default:"DEFAULT"
};

function escape(value, field) {
  if (value && value._isSequelizeMethod) {
    return value.toString();
  } else {
    return SqlString.escape(value, false, _options.timezone, _dialect, field);
  }
}

function quoteIdentifier(identifier, force) {
  if (identifier === '*') return identifier;
  return Utils.addTicks(identifier, '"');
}

/*
  Split an identifier into .-separated tokens and quote each part
*/
function quoteIdentifiers(identifiers, force) {
  if (identifiers.indexOf('.') !== -1) {
    identifiers = identifiers.split('.');
    return quoteIdentifier(identifiers.slice(0, identifiers.length - 1).join('.'))
      + '.' + quoteIdentifier(identifiers[identifiers.length - 1]);
  } else {
    return quoteIdentifier(identifiers);
  }
}

function wrapSingleQuote(identifier){
  return Utils.addTicks(identifier, "'");
}

function nameIndexes(indexes, rawTablename) {
  return Utils._.map(indexes, function (index) {
    if (!index.hasOwnProperty('name')) {
      var onlyAttributeNames = index.fields.map(function(attribute) {
        return (typeof attribute === 'string') ? attribute : attribute.attribute;
      }.bind(this));

      index.name = Utils.inflection.underscore(rawTablename + '_' + onlyAttributeNames.join('_'));
    }

    return index;
  });
}

function fieldsToSql(fields, singleQuote){
  var fieldStr = [];
  for (var key in fields) {
    if (fields.hasOwnProperty(key)) {
      if(singleQuote){
        fieldStr.push(wrapSingleQuote(key));
      }else{
        fieldStr.push(quoteIdentifier(key));
      }
    }
  }
  if(fieldStr){
    if(fieldStr.length > 0){
      return fieldStr.join(',');
    }
  }
  return '';
}

function processValue(val, modelAttribute){
  var sql;
  if(val instanceof Utils.cast){
    sql = 'CAST(';
    if(val.val._isSequelizeMethod){
      sql += processValue(val.val, modelAttribute) + ' AS ' + val.type.toUpperCase();
    }else{
      sql += escape(val.val) + ' AS ' + val.type.toUpperCase();
    }
    return sql + ')';
  } else if(val instanceof Utils.literal){
    return val.val;
  } else if (val instanceof Utils.fn) {
    sql = val.fn + '(' + val.args.map(function(arg) {
      if (arg._isSequelizeMethod) {
        return processValue(arg, modelAttribute);
      } else{
        return escape(arg);
      }
    }).join(', ') + ')';
    return sql;
  } else if (val === true || val === false){
    return wrapSingleQuote(val.toString());
  } else if (val instanceof Utils.col) {
    if (Array.isArray(val.col)) {
      if (!modelAttribute) {
        throw new Error('Cannot call Sequelize.col() with array outside of order / group clause');
      }
    } else if (val.col.indexOf('*') === 0) {
      return '*';
    }
    return quoteIdentifier(val.col);
  } else{
    return escape(val, modelAttribute);
  }
}

function valuesToSql(fields, modelAttributeMap, isUpdate){
  var values = [];
  for (var key in fields) {
    if (fields.hasOwnProperty(key)) {
      if(isUpdate){
        values.push(quoteIdentifier(key) + '=' + processValue(fields[key], (modelAttributeMap && modelAttributeMap[key]) || undefined));
      } else {
        values.push(processValue(fields[key], (modelAttributeMap && modelAttributeMap[key]) || undefined));
      }
    }
  }
  if(values){
    if(values.length > 0){
      return values.join(',');
    }
  }
  return '';
}

function loadColumn(attributes){
  var attrStr = [];
  for (var attr in attributes) {
    var dataType = attributes[attr];
    attrStr.push(quoteIdentifier(dataType));
  }
  return attrStr;
}

function addTableExistsWrapper(query, exists){
  return [
    "IF (",
      (exists ? "" : "NOT"), " EXISTS (",
      "SELECT * FROM INFORMATION_SCHEMA.TABLES",
      "WHERE TABLE_NAME='<%= unquotedTable %>'))",
    "BEGIN",
      query,
    "END"
  ].join(" ");
}

//select stuff
function loadFields(attributes){
  var attrStr = [];
  for (var attr in attributes) {
    attrStr.push(quoteIdentifier(attr));
  }
  return attrStr;
}

function processField(attribute, tableName){
  var sql = '';
  if(tableName){
    sql += quoteIdentifier(tableName) + '.';
  }
  if(attribute[0] !== attribute[1]){
    return sql + quoteIdentifier(attribute[0]) + ' AS ' + quoteIdentifier(attribute[1]);
   }else{
    return sql + quoteIdentifier(attribute[0]);
  }
}

function loadFieldsWithName(attributes, tableName){
  var attrStr = [];
  if(Array.isArray(attributes[0])){
    for (var i = 0; i < attributes.length; i++) {
      attrStr.push(processField(attributes[i], tableName));
    }
  }else{
    for (var attr in attributes) {
      if(tableName){
        attrStr.push(quoteIdentifier(tableName) + "." + quoteIdentifier(attr));
      }else{
        attrStr.push(quoteIdentifier(attr));
      }
    }
  }
  return attrStr.join(',');
}

function joinFields(attributes, tableName){
  var attrStr = [];
  if(tableName){
    for (var attr in attributes) {
      attrStr.push(quoteIdentifier(tableName)
        + "."
        + quoteIdentifier(attr)
        + " AS " + quoteIdentifier(tableName + "." + attr));
    }
  }
  return attrStr.join(',');
}

module.exports = {
  get options(){
    return _options;
  },

  set options(opt) {
    _options = opt;
  },

  get dialect(){
    return _dialect;
  },

  set dialect(dial) {
    _dialect = dial;
  },

  get sequelize(){
    return _sequelize;
  },

  set sequelize(seq) {
    _sequelize = seq;
  },

  quoteIdentifier: function(val){
    return quoteIdentifier(val);
  },

  quoteIdentifiers: function(val, force){
    return quoteIdentifiers(val, force);
  },

  escape: function(value, field) {
    return escape(value,field);
  },

  showTableSql: function(){
    return 'SELECT name FROM sys.Tables;';
  },

  processValue: function(val, modelAttribute){
    return processValue(val, modelAttribute);
  },

  quoteTable: function(param, as) {
    var table = '';
    if (as === true) {
      as = param.as || param.name || param;
    }

    if (_.isObject(param)) {
      if (param.schema) {
        table += param.schema + (param.delimiter || '.');
      }
      table += param.tableName;
      table = quoteIdentifier(table);
    } else {
      table = quoteIdentifier(param);
    }

    if (as) {
      table += ' AS ' + quoteIdentifier(as);
    }
    return table;
  },

  identityInsertWrapper: function(query, table){
    return[
      'SET IDENTITY_INSERT', quoteIdentifier(table), 'ON;',
      query,
      'SET IDENTITY_INSERT', quoteIdentifier(table), 'OFF;',
    ].join(' ');
  },

  getCreateSchemaSql: function(schema){
    return [
      'IF NOT EXISTS (SELECT schema_name',
      'FROM information_schema.schemata',
      'WHERE schema_name = ', wrapSingleQuote(schema), ')',
      'BEGIN',
        'EXEC sp_executesql N\'CREATE SCHEMA', quoteIdentifier(schema),';\'',
      "END;"].join(' ');
  },

  getCreateTableSql: function(tableName, attributes, options) {
    var query = "CREATE TABLE <%= tableName %> (<%= attributes%>)";
    var attrStr     = []
      , self        = this
      , primaryKeys = Utils._.keys(Utils._.pick(attributes, function(dataType){
        return dataType.indexOf('PRIMARY KEY') >= 0;
      }));

    for (var attr in attributes) {
      var dataType = attributes[attr];
      attrStr.push(quoteIdentifier(attr) + " " + dataType);
    }
    var values = {
      unquotedTable: tableName,
      tableName: quoteIdentifier(tableName.toString()),
      attributes: attrStr.join(", ")
    };
    query = addTableExistsWrapper(query);
    return Utils._.template(query)(values).trim() + ";";
  },

  alterTableSql: function(tableName){
    var query = 'ALTER TABLE <%= tableName %>';
    var value = {
      tableName : quoteIdentifier(tableName)
    };
    return Utils._.template(query)(value);
  },

  dropTableSql: function(tableName, options){
    var query = "DROP TABLE <%= tableName %>";
    var values ={};
    values = {
      unquotedTable: tableName,
      tableName: quoteIdentifier(tableName.toString())
    };

    query = addTableExistsWrapper(query, true);
    return Utils._.template(query)(values).trim() + ";";
  },

  insertSql: function(tableName, valueHash, modelAttributeMap) {
    var query
      , valueQuery = 'INSERT INTO <%= tableName %> (<%= attributes %>)'
      , emptyQuery = 'INSERT INTO <%= tableName %>';

    valueQuery += ' OUTPUT <%= selFields %>  VALUES (<%= values %>)';
    if(modelAttributeMap){
      emptyQuery += ' OUTPUT <%= selFields %>';
    }
    emptyQuery += ' DEFAULT VALUES';

    valueHash = Utils.removeNullValuesFromHash(valueHash, _options.omitNull);

    var selFields = [];
    var insertKey = false;
    for (var key in modelAttributeMap) {
      if (Utils._.isFunction(modelAttributeMap[key].type) &&
          modelAttributeMap[key].type() === undefined) // VIRTUAL field
        continue;

      selFields.push('INSERTED.' + quoteIdentifier((modelAttributeMap[key].field || key)));
      if (modelAttributeMap[key].autoIncrement &&
          (valueHash[key] === 'DEFAULT' || valueHash[key] === null)) {
        delete valueHash[key];
      } else if(valueHash[key] && modelAttributeMap[key].autoIncrement) {
        insertKey = true;
      }
    }

    var replacements = {
      tableName: quoteIdentifier(tableName.toString()),
      attributes: fieldsToSql(valueHash, false),
      selFields: selFields.join(','),
      values: valuesToSql(valueHash, modelAttributeMap)
    };

    query = (replacements.attributes.length ? valueQuery : emptyQuery) + ';';

    if(insertKey){
      query = this.identityInsertWrapper(query, tableName);
    }
    return Utils._.template(query)(replacements);
  },

  updateSql: function(tableName, valueHash, where, options, attributes){
    options = options || {};
{'fraction_non_alphanumeric': 0.1555229716520039, 'fraction_numerical': 0.0016617790811339198, 'mean_word_length': 3.1519886363636362, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, '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': '5545729', 'n_tokens_mistral': 6518, 'n_tokens_neox': 6325, 'n_words': 1324}