不要怂,就是干,撸起袖子干!

Commit b9bdc1d4 by Felix Becker Committed by Jan Aagaard Meier

ES6 refactor of utils.js (#6059)

- let, const, arrow functions, property shorthands, exports, classes
 - changes classes to be PascalCase
 - Removes inherit() function (not used anymore)
1 parent 49a7e543
...@@ -1098,9 +1098,9 @@ const QueryGenerator = { ...@@ -1098,9 +1098,9 @@ const QueryGenerator = {
if (Array.isArray(attr) && attr.length === 2) { if (Array.isArray(attr) && attr.length === 2) {
if (attr[0]._isSequelizeMethod) { if (attr[0]._isSequelizeMethod) {
if (attr[0] instanceof Utils.literal || if (attr[0] instanceof Utils.Literal ||
attr[0] instanceof Utils.cast || attr[0] instanceof Utils.Cast ||
attr[0] instanceof Utils.fn attr[0] instanceof Utils.Fn
) { ) {
verbatim = true; verbatim = true;
} }
...@@ -1110,9 +1110,9 @@ const QueryGenerator = { ...@@ -1110,9 +1110,9 @@ const QueryGenerator = {
attrAs = attr[1]; attrAs = attr[1];
attr = attr[0]; attr = attr[0];
} else if (attr instanceof Utils.literal) { } else if (attr instanceof Utils.Literal) {
return attr.val; // We trust the user to rename the field correctly return attr.val; // We trust the user to rename the field correctly
} else if (attr instanceof Utils.cast || attr instanceof Utils.fn) { } else if (attr instanceof Utils.Cast || attr instanceof Utils.Fn) {
throw new Error( throw new Error(
'Tried to select attributes using Sequelize.cast or Sequelize.fn without specifying an alias for the result, during eager loading. ' + 'Tried to select attributes using Sequelize.cast or Sequelize.fn without specifying an alias for the result, during eager loading. ' +
'This means the attribute will not be added to the returned instance' 'This means the attribute will not be added to the returned instance'
...@@ -1503,7 +1503,7 @@ const QueryGenerator = { ...@@ -1503,7 +1503,7 @@ const QueryGenerator = {
const subQueryOrder = []; const subQueryOrder = [];
const validateOrder = order => { const validateOrder = order => {
if (order instanceof Utils.literal) return; if (order instanceof Utils.Literal) return;
if (!_.includes([ if (!_.includes([
'ASC', 'ASC',
...@@ -1538,7 +1538,7 @@ const QueryGenerator = { ...@@ -1538,7 +1538,7 @@ const QueryGenerator = {
mainQueryOrder.push(this.quote(t, model)); mainQueryOrder.push(this.quote(t, model));
} }
} else { } else {
mainQueryOrder.push(this.quote(typeof options.order === 'string' ? new Utils.literal(options.order) : options.order, model)); mainQueryOrder.push(this.quote(typeof options.order === 'string' ? new Utils.Literal(options.order) : options.order, model));
} }
return {mainQueryOrder, subQueryOrder}; return {mainQueryOrder, subQueryOrder};
...@@ -1757,7 +1757,7 @@ const QueryGenerator = { ...@@ -1757,7 +1757,7 @@ const QueryGenerator = {
handleSequelizeMethod(smth, tableName, factory, options, prepend) { handleSequelizeMethod(smth, tableName, factory, options, prepend) {
let result; let result;
if (smth instanceof Utils.where) { if (smth instanceof Utils.Where) {
let value = smth.logic; let value = smth.logic;
let key; let key;
...@@ -1784,9 +1784,9 @@ const QueryGenerator = { ...@@ -1784,9 +1784,9 @@ const QueryGenerator = {
result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join(' ' + smth.comparator + ' '); result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join(' ' + smth.comparator + ' ');
} }
} else if (smth instanceof Utils.literal) { } else if (smth instanceof Utils.Literal) {
result = smth.val; result = smth.val;
} else if (smth instanceof Utils.cast) { } else if (smth instanceof Utils.Cast) {
if (smth.val._isSequelizeMethod) { if (smth.val._isSequelizeMethod) {
result = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend); result = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend);
} else { } else {
...@@ -1794,7 +1794,7 @@ const QueryGenerator = { ...@@ -1794,7 +1794,7 @@ const QueryGenerator = {
} }
result = 'CAST(' + result + ' AS ' + smth.type.toUpperCase() + ')'; result = 'CAST(' + result + ' AS ' + smth.type.toUpperCase() + ')';
} else if (smth instanceof Utils.fn) { } else if (smth instanceof Utils.Fn) {
result = smth.fn + '(' + smth.args.map(arg => { result = smth.fn + '(' + smth.args.map(arg => {
if (arg._isSequelizeMethod) { if (arg._isSequelizeMethod) {
return this.handleSequelizeMethod(arg, tableName, factory, options, prepend); return this.handleSequelizeMethod(arg, tableName, factory, options, prepend);
...@@ -1802,7 +1802,7 @@ const QueryGenerator = { ...@@ -1802,7 +1802,7 @@ const QueryGenerator = {
return this.escape(arg); return this.escape(arg);
} }
}).join(', ') + ')'; }).join(', ') + ')';
} else if (smth instanceof Utils.col) { } else if (smth instanceof Utils.Col) {
if (Array.isArray(smth.col)) { if (Array.isArray(smth.col)) {
if (!factory) { if (!factory) {
throw new Error('Cannot call Sequelize.col() with array outside of order / group clause'); throw new Error('Cannot call Sequelize.col() with array outside of order / group clause');
...@@ -1949,7 +1949,7 @@ const QueryGenerator = { ...@@ -1949,7 +1949,7 @@ const QueryGenerator = {
} }
} }
if (value && value._isSequelizeMethod && !(key !== undefined && value instanceof Utils.fn)) { if (value && value._isSequelizeMethod && !(key !== undefined && value instanceof Utils.Fn)) {
return this.handleSequelizeMethod(value); return this.handleSequelizeMethod(value);
} }
...@@ -2025,7 +2025,7 @@ const QueryGenerator = { ...@@ -2025,7 +2025,7 @@ const QueryGenerator = {
let $baseKey = this.quoteIdentifier(key)+'#>>\'{'+path.join(', ')+'}\''; let $baseKey = this.quoteIdentifier(key)+'#>>\'{'+path.join(', ')+'}\'';
if (options.prefix) { if (options.prefix) {
if (options.prefix instanceof Utils.literal) { if (options.prefix instanceof Utils.Literal) {
$baseKey = this.handleSequelizeMethod(options.prefix)+'.'+$baseKey; $baseKey = this.handleSequelizeMethod(options.prefix)+'.'+$baseKey;
} else { } else {
$baseKey = this.quoteTable(options.prefix)+'.'+$baseKey; $baseKey = this.quoteTable(options.prefix)+'.'+$baseKey;
...@@ -2060,7 +2060,7 @@ const QueryGenerator = { ...@@ -2060,7 +2060,7 @@ const QueryGenerator = {
$where[$prop] = $item; $where[$prop] = $item;
const $key = castKey($item); const $key = castKey($item);
$items.push(this.whereItemQuery(new Utils.literal($key), $where/*, _.pick(options, 'prefix')*/)); $items.push(this.whereItemQuery(new Utils.Literal($key), $where/*, _.pick(options, 'prefix')*/));
} else { } else {
traverse($prop, $item, path.concat([$prop])); traverse($prop, $item, path.concat([$prop]));
} }
...@@ -2069,7 +2069,7 @@ const QueryGenerator = { ...@@ -2069,7 +2069,7 @@ const QueryGenerator = {
$where.$eq = item; $where.$eq = item;
const $key = castKey(item); const $key = castKey(item);
$items.push(this.whereItemQuery(new Utils.literal($key), $where/*, _.pick(options, 'prefix')*/)); $items.push(this.whereItemQuery(new Utils.Literal($key), $where/*, _.pick(options, 'prefix')*/));
} }
}; };
...@@ -2125,7 +2125,7 @@ const QueryGenerator = { ...@@ -2125,7 +2125,7 @@ const QueryGenerator = {
comparator = 'IN'; comparator = 'IN';
if (value.$notIn) comparator = 'NOT IN'; if (value.$notIn) comparator = 'NOT IN';
if ((value.$in || value.$notIn) instanceof Utils.literal) { if ((value.$in || value.$notIn) instanceof Utils.Literal) {
value = (value.$in || value.$notIn).val; value = (value.$in || value.$notIn).val;
} else if ((value.$in || value.$notIn).length) { } else if ((value.$in || value.$notIn).length) {
value = '('+(value.$in || value.$notIn).map(item => this.escape(item)).join(', ')+')'; value = '('+(value.$in || value.$notIn).map(item => this.escape(item)).join(', ')+')';
...@@ -2226,7 +2226,7 @@ const QueryGenerator = { ...@@ -2226,7 +2226,7 @@ const QueryGenerator = {
} }
if (options.prefix && prefix) { if (options.prefix && prefix) {
if (options.prefix instanceof Utils.literal) { if (options.prefix instanceof Utils.Literal) {
key = [this.handleSequelizeMethod(options.prefix), key].join('.'); key = [this.handleSequelizeMethod(options.prefix), key].join('.');
} else { } else {
key = [this.quoteTable(options.prefix), key].join('.'); key = [this.quoteTable(options.prefix), key].join('.');
......
...@@ -124,7 +124,7 @@ const QueryGenerator = { ...@@ -124,7 +124,7 @@ const QueryGenerator = {
}, },
handleSequelizeMethod(smth, tableName, factory, options, prepend) { handleSequelizeMethod(smth, tableName, factory, options, prepend) {
if (smth instanceof Utils.json) { if (smth instanceof Utils.Json) {
// Parse nested object // Parse nested object
if (smth.conditions) { if (smth.conditions) {
const conditions = _.map(this.parseConditionObject(smth.conditions), condition => const conditions = _.map(this.parseConditionObject(smth.conditions), condition =>
......
...@@ -890,7 +890,7 @@ class Sequelize { ...@@ -890,7 +890,7 @@ class Sequelize {
* @return {Sequelize.fn} * @return {Sequelize.fn}
*/ */
static fn(fn) { static fn(fn) {
return new Utils.fn(fn, Utils.sliceArgs(arguments, 1)); return new Utils.Fn(fn, Utils.sliceArgs(arguments, 1));
} }
/** /**
...@@ -903,7 +903,7 @@ class Sequelize { ...@@ -903,7 +903,7 @@ class Sequelize {
* @return {Sequelize.col} * @return {Sequelize.col}
*/ */
static col(col) { static col(col) {
return new Utils.col(col); return new Utils.Col(col);
} }
/** /**
...@@ -916,7 +916,7 @@ class Sequelize { ...@@ -916,7 +916,7 @@ class Sequelize {
* @return {Sequelize.cast} * @return {Sequelize.cast}
*/ */
static cast(val, type) { static cast(val, type) {
return new Utils.cast(val, type); return new Utils.Cast(val, type);
} }
/** /**
...@@ -929,7 +929,7 @@ class Sequelize { ...@@ -929,7 +929,7 @@ class Sequelize {
* @return {Sequelize.literal} * @return {Sequelize.literal}
*/ */
static literal(val) { static literal(val) {
return new Utils.literal(val); return new Utils.Literal(val);
} }
/** /**
...@@ -968,7 +968,7 @@ class Sequelize { ...@@ -968,7 +968,7 @@ class Sequelize {
* @return {Sequelize.json} * @return {Sequelize.json}
*/ */
static json(conditionsOrPath, value) { static json(conditionsOrPath, value) {
return new Utils.json(conditionsOrPath, value); return new Utils.Json(conditionsOrPath, value);
} }
/** /**
...@@ -990,7 +990,7 @@ class Sequelize { ...@@ -990,7 +990,7 @@ class Sequelize {
* @return {Sequelize.where} * @return {Sequelize.where}
*/ */
static where(attr, comparator, logic) { static where(attr, comparator, logic) {
return new Utils.where(attr, comparator, logic); return new Utils.Where(attr, comparator, logic);
} }
/** /**
......
'use strict'; 'use strict';
var DataTypes = require('./data-types') const DataTypes = require('./data-types');
, SqlString = require('./sql-string') const SqlString = require('./sql-string');
, _ = require('lodash').runInContext() // Prevent anyone messing with template settings by creating a fresh copy const _ = require('lodash').runInContext(); // Prevent anyone messing with template settings by creating a fresh copy
, parameterValidator = require('./utils/parameter-validator') const parameterValidator = require('./utils/parameter-validator');
, inflection = require('inflection') const inflection = require('inflection');
, uuid = require('node-uuid') const uuid = require('node-uuid');
, primitives = ['string', 'number', 'boolean']; const Promise = require('./promise');
const primitives = ['string', 'number', 'boolean'];
var Utils = module.exports = {
inflection: inflection, exports.Promise = Promise;
_: _, exports._ = _;
camelizeIf: function(string, condition) { exports.inflection = inflection;
var result = string;
function camelizeIf(string, condition) {
if (condition) { let result = string;
result = Utils.camelize(string);
if (condition) {
result = camelize(string);
}
return result;
}
exports.camelizeIf = camelizeIf;
function underscoredIf(string, condition) {
let result = string;
if (condition) {
result = inflection.underscore(string);
}
return result;
}
exports.underscoredIf = underscoredIf;
function isPrimitive(val) {
return primitives.indexOf(typeof val) !== -1;
}
exports.isPrimitive = isPrimitive;
// Same concept as _.merge, but don't overwrite properties that have already been assigned
function mergeDefaults(a, b) {
return _.mergeWith(a, b, (objectValue, sourceValue) => {
// If it's an object, let _ handle it this time, we will be called again for each property
if (!this._.isPlainObject(objectValue) && objectValue !== undefined) {
return objectValue;
} }
});
return result; }
}, exports.mergeDefaults = mergeDefaults;
underscoredIf: function(string, condition) {
var result = string; // An alternative to _.merge, which doesn't clone its arguments
// Cloning is a bad idea because options arguments may contain references to sequelize
if (condition) { // models - which again reference database libs which don't like to be cloned (in particular pg-native)
result = inflection.underscore(string); function merge() {
} const result = {};
return result; for (const obj of arguments) {
}, _.forOwn(obj, (value, key) => {
isPrimitive: function (val) { if (typeof value !== 'undefined') {
return primitives.indexOf(typeof val) !== -1; if (!result[key]) {
}, result[key] = value;
// Same concept as _.merge, but don't overwrite properties that have already been assigned } else if (_.isPlainObject(value) && _.isPlainObject(result[key])) {
mergeDefaults: function (a, b) { result[key] = merge(result[key], value);
return _.mergeWith(a, b, function (objectValue, sourceValue) { } else if (Array.isArray(value) && Array.isArray(result[key])) {
// If it's an object, let _ handle it this time, we will be called again for each property result[key] = value.concat(result[key]);
if (!this._.isPlainObject(objectValue) && objectValue !== undefined) { } else {
return objectValue; result[key] = value;
}
}.bind(this));
},
// An alternative to _.merge, which doesn't clone its arguments
// Cloning is a bad idea because options arguments may contain references to sequelize
// models - which again reference database libs which don't like to be cloned (in particular pg-native)
merge: function () {
var result = {};
Array.prototype.slice.apply(arguments).forEach(function (obj) {
_.forOwn(obj, function (value, key) {
if (typeof value !== 'undefined') {
if (!result[key]) {
result[key] = value;
} else if (_.isPlainObject(value) && _.isPlainObject(result[key])) {
result[key] = Utils.merge(result[key], value);
} else if (Array.isArray(value) && Array.isArray(result[key])) {
result[key] = value.concat(result[key]);
} else {
result[key] = value;
}
} }
});
});
return result;
},
lowercaseFirst: function (s) {
return s[0].toLowerCase() + s.slice(1);
},
uppercaseFirst: function (s) {
return s[0].toUpperCase() + s.slice(1);
},
spliceStr: function (str, index, count, add) {
return str.slice(0, index) + add + str.slice(index + count);
},
camelize: function(str){
return str.trim().replace(/[-_\s]+(.)?/g, function(match, c){ return c.toUpperCase(); });
},
format: function(arr, dialect) {
var timeZone = null;
// Make a clone of the array beacuse format modifies the passed args
return SqlString.format(arr[0], arr.slice(1), timeZone, dialect);
},
formatNamedParameters: function(sql, parameters, dialect) {
var timeZone = null;
return SqlString.formatNamedParameters(sql, parameters, timeZone, dialect);
},
cloneDeep: function(obj) {
obj = obj || {};
return _.cloneDeepWith(obj, function (elem) {
// Do not try to customize cloning of arrays or POJOs
if (Array.isArray(elem) || _.isPlainObject(elem)) {
return undefined;
}
// Don't clone stuff that's an object, but not a plain one - fx example sequelize models and instances
if (typeof elem === 'object') {
return elem;
}
// Preserve special data-types like `fn` across clones. _.get() is used for checking up the prototype chain
if (elem && typeof elem.clone === 'function') {
return elem.clone();
} }
}); });
}, }
/* Expand and normalize finder options */ return result;
mapFinderOptions: function(options, Model) { }
if (Model._hasVirtualAttributes && Array.isArray(options.attributes)) { exports.merge = merge;
options.attributes.forEach(function (attribute) {
if (Model._isVirtualAttribute(attribute) && Model.rawAttributes[attribute].type.fields) { function lowercaseFirst(s) {
options.attributes = options.attributes.concat(Model.rawAttributes[attribute].type.fields); return s[0].toLowerCase() + s.slice(1);
} }
}.bind(Model)); exports.lowercaseFirst = lowercaseFirst;
options.attributes = _.without.apply(_, [options.attributes].concat(Model._virtualAttributes));
options.attributes = _.uniq(options.attributes); function uppercaseFirst(s) {
return s[0].toUpperCase() + s.slice(1);
}
exports.uppercaseFirst = uppercaseFirst;
function spliceStr(str, index, count, add) {
return str.slice(0, index) + add + str.slice(index + count);
}
exports.spliceStr = spliceStr;
function camelize(str) {
return str.trim().replace(/[-_\s]+(.)?/g, (match, c) => c.toUpperCase());
}
exports.camelize = camelize;
function format(arr, dialect) {
const timeZone = null;
// Make a clone of the array beacuse format modifies the passed args
return SqlString.format(arr[0], arr.slice(1), timeZone, dialect);
}
exports.format = format;
function formatNamedParameters(sql, parameters, dialect) {
const timeZone = null;
return SqlString.formatNamedParameters(sql, parameters, timeZone, dialect);
}
exports.formatNamedParameters = formatNamedParameters;
function cloneDeep(obj) {
obj = obj || {};
return _.cloneDeepWith(obj, elem => {
// Do not try to customize cloning of arrays or POJOs
if (Array.isArray(elem) || _.isPlainObject(elem)) {
return undefined;
} }
Utils.mapOptionFieldNames(options, Model); // Don't clone stuff that's an object, but not a plain one - fx example sequelize models and instances
if (typeof elem === 'object') {
return options; return elem;
},
/* Used to map field names in attributes and where conditions */
mapOptionFieldNames: function(options, Model) {
if (Array.isArray(options.attributes)) {
options.attributes = options.attributes.map(function(attr) {
// Object lookups will force any variable to strings, we don't want that for special objects etc
if (typeof attr !== 'string') return attr;
// Map attributes to aliased syntax attributes
if (Model.rawAttributes[attr] && attr !== Model.rawAttributes[attr].field) {
return [Model.rawAttributes[attr].field, attr];
}
return attr;
});
} }
if (options.where && _.isPlainObject(options.where)) { // Preserve special data-types like `fn` across clones. _.get() is used for checking up the prototype chain
options.where = Utils.mapWhereFieldNames(options.where, Model); if (elem && typeof elem.clone === 'function') {
return elem.clone();
} }
});
if (Array.isArray(options.order)) { }
options.order.forEach(function(oGroup) { exports.cloneDeep = cloneDeep;
var OrderModel, attr, attrOffset;
/* Expand and normalize finder options */
if (Array.isArray(oGroup)) { function mapFinderOptions(options, Model) {
OrderModel = Model; if (Model._hasVirtualAttributes && Array.isArray(options.attributes)) {
for (const attribute of options.attributes) {
// Check if we have ['attr', 'DESC'] or [Model, 'attr', 'DESC'] if (Model._isVirtualAttribute(attribute) && Model.rawAttributes[attribute].type.fields) {
if (typeof oGroup[oGroup.length - 2] === 'string') { options.attributes = options.attributes.concat(Model.rawAttributes[attribute].type.fields);
attrOffset = 2; }
// Assume ['attr'], [Model, 'attr'] or [seq.fn('somefn', 1), 'DESC']
} else {
attrOffset = 1;
}
attr = oGroup[oGroup.length - attrOffset];
if (oGroup.length > attrOffset) {
OrderModel = oGroup[oGroup.length - (attrOffset + 1)];
if (OrderModel.model) {
OrderModel = OrderModel.model;
}
}
if (OrderModel.rawAttributes && OrderModel.rawAttributes[attr] && attr !== OrderModel.rawAttributes[attr].field) {
oGroup[oGroup.length - attrOffset] = OrderModel.rawAttributes[attr].field;
}
}
});
} }
options.attributes = _.without.apply(_, [options.attributes].concat(Model._virtualAttributes));
options.attributes = _.uniq(options.attributes);
}
mapOptionFieldNames(options, Model);
return options;
}
exports.mapFinderOptions = mapFinderOptions;
/* Used to map field names in attributes and where conditions */
function mapOptionFieldNames(options, Model) {
if (Array.isArray(options.attributes)) {
options.attributes = options.attributes.map(attr => {
// Object lookups will force any variable to strings, we don't want that for special objects etc
if (typeof attr !== 'string') return attr;
// Map attributes to aliased syntax attributes
if (Model.rawAttributes[attr] && attr !== Model.rawAttributes[attr].field) {
return [Model.rawAttributes[attr].field, attr];
}
return attr;
});
}
return options; if (options.where && _.isPlainObject(options.where)) {
}, options.where = mapWhereFieldNames(options.where, Model);
}
mapWhereFieldNames: function (attributes, Model) { if (Array.isArray(options.order)) {
var attribute for (const oGroup of options.order) {
, rawAttribute; let OrderModel;
let attr;
let attrOffset;
if (attributes) { if (Array.isArray(oGroup)) {
for (attribute in attributes) { OrderModel = Model;
rawAttribute = Model.rawAttributes[attribute];
if (rawAttribute && rawAttribute.field !== rawAttribute.fieldName) { // Check if we have ['attr', 'DESC'] or [Model, 'attr', 'DESC']
attributes[rawAttribute.field] = attributes[attribute]; if (typeof oGroup[oGroup.length - 2] === 'string') {
delete attributes[attribute]; attrOffset = 2;
}
if (_.isPlainObject(attributes[attribute])) { // Assume ['attr'], [Model, 'attr'] or [seq.fn('somefn', 1), 'DESC']
attributes[attribute] = Utils.mapOptionFieldNames({ } else {
where: attributes[attribute] attrOffset = 1;
}, Model).where;
} }
if (Array.isArray(attributes[attribute])) { attr = oGroup[oGroup.length - attrOffset];
attributes[attribute] = attributes[attribute].map(function (where) { if (oGroup.length > attrOffset) {
if (_.isPlainObject(where)) { OrderModel = oGroup[oGroup.length - (attrOffset + 1)];
return Utils.mapWhereFieldNames(where, Model); if (OrderModel.model) {
} OrderModel = OrderModel.model;
}
}
return where; if (OrderModel.rawAttributes && OrderModel.rawAttributes[attr] && attr !== OrderModel.rawAttributes[attr].field) {
}); oGroup[oGroup.length - attrOffset] = OrderModel.rawAttributes[attr].field;
} }
} }
} }
}
return attributes; return options;
}, }
exports.mapOptionFieldNames = mapOptionFieldNames;
/* Used to map field names in values */ function mapWhereFieldNames(attributes, Model) {
mapValueFieldNames: function (dataValues, fields, Model) { let attribute;
var values = {}; let rawAttribute;
fields.forEach(function(attr) { if (attributes) {
if (dataValues[attr] !== undefined && !Model._isVirtualAttribute(attr)) { for (attribute in attributes) {
// Field name mapping rawAttribute = Model.rawAttributes[attribute];
if (Model.rawAttributes[attr] && Model.rawAttributes[attr].field && Model.rawAttributes[attr].field !== attr) {
values[Model.rawAttributes[attr].field] = dataValues[attr];
} else {
values[attr] = dataValues[attr];
}
}
});
return values; if (rawAttribute && rawAttribute.field !== rawAttribute.fieldName) {
}, attributes[rawAttribute.field] = attributes[attribute];
delete attributes[attribute];
isColString: function(value) {
return typeof value === 'string' && value.substr(0, 1) === '$' && value.substr(value.length - 1, 1) === '$';
},
argsArePrimaryKeys: function(args, primaryKeys) {
var result = (args.length === Object.keys(primaryKeys).length);
if (result) {
Utils._.each(args, function(arg) {
if (result) {
if (['number', 'string'].indexOf(typeof arg) !== -1) {
result = true;
} else {
result = (arg instanceof Date) || Buffer.isBuffer(arg);
}
}
});
}
return result;
},
canTreatArrayAsAnd: function(arr) {
return arr.reduce(function(treatAsAnd, arg) {
if (treatAsAnd) {
return treatAsAnd;
} else {
return Utils._.isPlainObject(arg);
} }
}, false);
},
combineTableNames: function(tableName1, tableName2) { if (_.isPlainObject(attributes[attribute])) {
return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1); attributes[attribute] = mapOptionFieldNames({
}, where: attributes[attribute]
}, Model).where;
}
singularize: function(s) { if (Array.isArray(attributes[attribute])) {
return inflection.singularize(s); attributes[attribute] = attributes[attribute].map(where => {
}, if (_.isPlainObject(where)) {
return mapWhereFieldNames(where, Model);
}
pluralize: function(s) { return where;
return inflection.pluralize(s); });
}, }
}
}
removeCommentsFromFunctionString: function(s) { return attributes;
s = s.replace(/\s*(\/\/.*)/g, ''); }
s = s.replace(/(\/\*[\n\r\s\S]*?\*\/)/mg, ''); exports.mapWhereFieldNames = mapWhereFieldNames;
return s; /* Used to map field names in values */
}, function mapValueFieldNames(dataValues, fields, Model) {
const values = {};
toDefaultValue: function(value) { for (const attr of fields) {
if (typeof value === 'function') { if (dataValues[attr] !== undefined && !Model._isVirtualAttribute(attr)) {
var tmp = value(); // Field name mapping
if (tmp instanceof DataTypes.ABSTRACT) { if (Model.rawAttributes[attr] && Model.rawAttributes[attr].field && Model.rawAttributes[attr].field !== attr) {
return tmp.toSql(); values[Model.rawAttributes[attr].field] = dataValues[attr];
} else { } else {
return tmp; values[attr] = dataValues[attr];
} }
} else if (value instanceof DataTypes.UUIDV1) {
return uuid.v1();
} else if (value instanceof DataTypes.UUIDV4) {
return uuid.v4();
} else if (value instanceof DataTypes.NOW) {
return Utils.now();
} else if(_.isPlainObject(value) || _.isArray(value)) {
return _.clone(value);
} else {
return value;
} }
}, }
/** return values;
* Determine if the default value provided exists and can be described }
* in a db schema using the DEFAULT directive. exports.mapValueFieldNames = mapValueFieldNames;
*
* @param {*} value Any default value. function isColString(value) {
* @return {boolean} yes / no. return typeof value === 'string' && value.substr(0, 1) === '$' && value.substr(value.length - 1, 1) === '$';
*/ }
defaultValueSchemable: function(value) { exports.isColString = isColString;
if (typeof value === 'undefined') { return false; }
function argsArePrimaryKeys(args, primaryKeys) {
// TODO this will be schemable when all supported db let result = (args.length === Object.keys(primaryKeys).length);
// have been normalized for this case if (result) {
if (value instanceof DataTypes.NOW) { return false; } _.each(args, arg => {
if (result) {
if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; } if (['number', 'string'].indexOf(typeof arg) !== -1) {
result = true;
if (_.isFunction(value)) { } else {
return false; result = (arg instanceof Date) || Buffer.isBuffer(arg);
}
return true;
},
removeNullValuesFromHash: function(hash, omitNull, options) {
var result = hash;
options = options || {};
options.allowNull = options.allowNull || [];
if (omitNull) {
var _hash = {};
Utils._.forIn(hash, function(val, key) {
if (options.allowNull.indexOf(key) > -1 || key.match(/Id$/) || ((val !== null) && (val !== undefined))) {
_hash[key] = val;
} }
}); }
});
result = _hash; }
} return result;
}
return result; exports.argsArePrimaryKeys = argsArePrimaryKeys;
},
function canTreatArrayAsAnd(arr) {
inherit: function(SubClass, SuperClass) { return arr.reduce((treatAsAnd, arg) => {
if (SuperClass.constructor === Function) { if (treatAsAnd) {
// Normal Inheritance return treatAsAnd;
SubClass.prototype = new SuperClass();
SubClass.prototype.constructor = SubClass;
SubClass.prototype.parent = SuperClass.prototype;
} else { } else {
// Pure Virtual Inheritance return _.isPlainObject(arg);
SubClass.prototype = SuperClass;
SubClass.prototype.constructor = SubClass;
SubClass.prototype.parent = SuperClass;
} }
}, false);
return SubClass; }
}, exports.canTreatArrayAsAnd = canTreatArrayAsAnd;
function combineTableNames(tableName1, tableName2) {
stack: function _stackGrabber() { return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1);
var orig = Error.prepareStackTrace; }
Error.prepareStackTrace = function(_, stack) { return stack; }; exports.combineTableNames = combineTableNames;
var err = new Error();
Error.captureStackTrace(err, _stackGrabber); function singularize(s) {
var errStack = err.stack; return inflection.singularize(s);
Error.prepareStackTrace = orig; }
return errStack; exports.singularize = singularize;
},
function pluralize(s) {
sliceArgs: function (args, begin) { return inflection.pluralize(s);
begin = begin || 0; }
var tmp = new Array(args.length - begin); exports.pluralize = pluralize;
for (var i = begin; i < args.length; ++i) {
tmp[i - begin] = args[i]; function removeCommentsFromFunctionString(s) {
s = s.replace(/\s*(\/\/.*)/g, '');
s = s.replace(/(\/\*[\n\r\s\S]*?\*\/)/mg, '');
return s;
}
exports.removeCommentsFromFunctionString = removeCommentsFromFunctionString;
function toDefaultValue(value) {
if (typeof value === 'function') {
const tmp = value();
if (tmp instanceof DataTypes.ABSTRACT) {
return tmp.toSql();
} else {
return tmp;
} }
return tmp; } else if (value instanceof DataTypes.UUIDV1) {
}, return uuid.v1();
} else if (value instanceof DataTypes.UUIDV4) {
return uuid.v4();
} else if (value instanceof DataTypes.NOW) {
return now();
} else if(_.isPlainObject(value) || _.isArray(value)) {
return _.clone(value);
} else {
return value;
}
}
exports.toDefaultValue = toDefaultValue;
/**
* Determine if the default value provided exists and can be described
* in a db schema using the DEFAULT directive.
*
* @param {*} value Any default value.
* @return {boolean} yes / no.
*/
function defaultValueSchemable(value) {
if (typeof value === 'undefined') { return false; }
// TODO this will be schemable when all supported db
// have been normalized for this case
if (value instanceof DataTypes.NOW) { return false; }
if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; }
if (_.isFunction(value)) {
return false;
}
return true;
}
exports.defaultValueSchemable = defaultValueSchemable;
function removeNullValuesFromHash(hash, omitNull, options) {
let result = hash;
options = options || {};
options.allowNull = options.allowNull || [];
if (omitNull) {
const _hash = {};
_.forIn(hash, (val, key) => {
if (options.allowNull.indexOf(key) > -1 || key.match(/Id$/) || ((val !== null) && (val !== undefined))) {
_hash[key] = val;
}
});
now: function(dialect) { result = _hash;
var now = new Date(); }
if (['postgres', 'sqlite'].indexOf(dialect) === -1) {
now.setMilliseconds(0); return result;
} }
return now; exports.removeNullValuesFromHash = removeNullValuesFromHash;
},
function stack() {
tick: function(func) { const orig = Error.prepareStackTrace;
var tick = (global.hasOwnProperty('setImmediate') ? global.setImmediate : process.nextTick); Error.prepareStackTrace = (_, stack) => stack;
tick(func); const err = new Error();
}, Error.captureStackTrace(err, stack);
const errStack = err.stack;
// Note: Use the `quoteIdentifier()` and `escape()` methods on the Error.prepareStackTrace = orig;
// `QueryInterface` instead for more portable code. return errStack;
}
TICK_CHAR: '`', exports.stack = stack;
addTicks: function(s, tickChar) {
tickChar = tickChar || Utils.TICK_CHAR; function sliceArgs(args, begin) {
return tickChar + Utils.removeTicks(s, tickChar) + tickChar; begin = begin || 0;
}, const tmp = new Array(args.length - begin);
removeTicks: function(s, tickChar) { for (let i = begin; i < args.length; ++i) {
tickChar = tickChar || Utils.TICK_CHAR; tmp[i - begin] = args[i];
return s.replace(new RegExp(tickChar, 'g'), ''); }
}, return tmp;
}
/* exports.sliceArgs = sliceArgs;
* Utility functions for representing SQL functions, and columns that should be escaped.
* Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead. function now(dialect) {
*/ const now = new Date();
fn: function(fn, args) { if (['postgres', 'sqlite'].indexOf(dialect) === -1) {
now.setMilliseconds(0);
}
return now;
}
exports.now = now;
// Note: Use the `quoteIdentifier()` and `escape()` methods on the
// `QueryInterface` instead for more portable code.
const TICK_CHAR = '`';
exports.TICK_CHAR = TICK_CHAR;
function addTicks(s, tickChar) {
tickChar = tickChar || TICK_CHAR;
return tickChar + removeTicks(s, tickChar) + tickChar;
}
exports.addTicks = addTicks;
function removeTicks(s, tickChar) {
tickChar = tickChar || TICK_CHAR;
return s.replace(new RegExp(tickChar, 'g'), '');
}
exports.removeTicks = removeTicks;
/**
* Utility functions for representing SQL functions, and columns that should be escaped.
* Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
*/
class Fn {
constructor(fn, args) {
this.fn = fn; this.fn = fn;
this.args = args; this.args = args;
}, }
clone() {
col: function(col) { return new Fn(this.fn, this.args);
}
}
exports.Fn = Fn;
class Col {
constructor(col) {
if (arguments.length > 1) { if (arguments.length > 1) {
col = this.sliceArgs(arguments); col = this.sliceArgs(arguments);
} }
this.col = col; this.col = col;
}, }
}
exports.Col = Col;
cast: function(val, type) { class Cast {
constructor(val, type) {
this.val = val; this.val = val;
this.type = (type || '').trim(); this.type = (type || '').trim();
}, }
}
exports.Cast = Cast;
literal: function(val) { class Literal {
constructor(val) {
this.val = val; this.val = val;
}, }
}
exports.Literal = Literal;
json: function(conditionsOrPath, value) { class Json {
if (Utils._.isObject(conditionsOrPath)) { constructor(conditionsOrPath, value) {
if (_.isObject(conditionsOrPath)) {
this.conditions = conditionsOrPath; this.conditions = conditionsOrPath;
} else { } else {
this.path = conditionsOrPath; this.path = conditionsOrPath;
...@@ -436,9 +480,12 @@ var Utils = module.exports = { ...@@ -436,9 +480,12 @@ var Utils = module.exports = {
this.value = value; this.value = value;
} }
} }
}, }
}
exports.Json = Json;
where: function(attribute, comparator, logic) { class Where {
constructor(attribute, comparator, logic) {
if (logic === undefined) { if (logic === undefined) {
logic = comparator; logic = comparator;
comparator = '='; comparator = '=';
...@@ -447,20 +494,15 @@ var Utils = module.exports = { ...@@ -447,20 +494,15 @@ var Utils = module.exports = {
this.attribute = attribute; this.attribute = attribute;
this.comparator = comparator; this.comparator = comparator;
this.logic = logic; this.logic = logic;
}, }
}
validateParameter: parameterValidator exports.Where = Where;
};
Where.prototype._isSequelizeMethod =
Utils.where.prototype._isSequelizeMethod = Literal.prototype._isSequelizeMethod =
Utils.literal.prototype._isSequelizeMethod = Cast.prototype._isSequelizeMethod =
Utils.cast.prototype._isSequelizeMethod = Fn.prototype._isSequelizeMethod =
Utils.fn.prototype._isSequelizeMethod = Col.prototype._isSequelizeMethod =
Utils.col.prototype._isSequelizeMethod = Json.prototype._isSequelizeMethod = true;
Utils.json.prototype._isSequelizeMethod = true;
exports.validateParameter = parameterValidator;
Utils.fn.prototype.clone = function() {
return new Utils.fn(this.fn, this.args);
};
Utils.Promise = require('./promise');
...@@ -130,8 +130,8 @@ describe(Support.getTestDialectTeaser('DAO'), function() { ...@@ -130,8 +130,8 @@ describe(Support.getTestDialectTeaser('DAO'), function() {
b: self.sequelize.col('always_false') b: self.sequelize.col('always_false')
}); });
expect(user.get('d')).to.be.instanceof(self.sequelize.Utils.fn); expect(user.get('d')).to.be.instanceof(self.sequelize.Utils.Fn);
expect(user.get('b')).to.be.instanceof(self.sequelize.Utils.col); expect(user.get('b')).to.be.instanceof(self.sequelize.Utils.Col);
return user.save().then(function() { return user.save().then(function() {
return user.reload().then(function() { return user.reload().then(function() {
......
...@@ -195,23 +195,23 @@ describe(Support.getTestDialectTeaser('Utils'), function() { ...@@ -195,23 +195,23 @@ describe(Support.getTestDialectTeaser('Utils'), function() {
another_json_field: { x: 1 } another_json_field: { x: 1 }
}; };
var expected = "metadata#>>'{language}' = 'icelandic' and metadata#>>'{pg_rating,dk}' = 'G' and another_json_field#>>'{x}' = '1'"; var expected = "metadata#>>'{language}' = 'icelandic' and metadata#>>'{pg_rating,dk}' = 'G' and another_json_field#>>'{x}' = '1'";
expect(queryGenerator.handleSequelizeMethod(new Utils.json(conditions))).to.deep.equal(expected); expect(queryGenerator.handleSequelizeMethod(new Utils.Json(conditions))).to.deep.equal(expected);
}); });
it('successfully parses a string using dot notation', function() { it('successfully parses a string using dot notation', function() {
var path = 'metadata.pg_rating.dk'; var path = 'metadata.pg_rating.dk';
expect(queryGenerator.handleSequelizeMethod(new Utils.json(path))).to.equal("metadata#>>'{pg_rating,dk}'"); expect(queryGenerator.handleSequelizeMethod(new Utils.Json(path))).to.equal("metadata#>>'{pg_rating,dk}'");
}); });
it('allows postgres json syntax', function() { it('allows postgres json syntax', function() {
var path = 'metadata->pg_rating->>dk'; var path = 'metadata->pg_rating->>dk';
expect(queryGenerator.handleSequelizeMethod(new Utils.json(path))).to.equal(path); expect(queryGenerator.handleSequelizeMethod(new Utils.Json(path))).to.equal(path);
}); });
it('can take a value to compare against', function() { it('can take a value to compare against', function() {
var path = 'metadata.pg_rating.is'; var path = 'metadata.pg_rating.is';
var value = 'U'; var value = 'U';
expect(queryGenerator.handleSequelizeMethod(new Utils.json(path, value))).to.equal("metadata#>>'{pg_rating,is}' = 'U'"); expect(queryGenerator.handleSequelizeMethod(new Utils.Json(path, value))).to.equal("metadata#>>'{pg_rating,is}' = 'U'");
}); });
}); });
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!