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

Commit 5fe47e52 by Ruben Bridgewater

Fix util.toDefaultValue

Fix typo

Fix updatedAt and createdAt not always being 100% identical

Use instanceof Abstract and remove __getTimestamp
1 parent 176e516a
# 3.1.0 # 3.1.0
- [BUG] Fix an issue with the build in isIP validator returning false negatives [#3756](https://github.com/sequelize/sequelize/pull/3756)
- [ADDED] It is now possible to defer constraints in PostgreSQL by added a property `deferrable` to the `references` object of a field. - [ADDED] It is now possible to defer constraints in PostgreSQL by added a property `deferrable` to the `references` object of a field.
- [BUG] Fix an issue with the build in isIP validator returning false negatives [#3756](https://github.com/sequelize/sequelize/pull/3756)
- [BUG] Fix regression in util.toDefaultValue not returning the data types [#3733](https://github.com/sequelize/sequelize/pull/3733)
# 3.0.1 # 3.0.1
......
...@@ -6,7 +6,8 @@ var Utils = require('../../utils') ...@@ -6,7 +6,8 @@ var Utils = require('../../utils')
, DataTypes = require('../../data-types') , DataTypes = require('../../data-types')
, _ = require('lodash') , _ = require('lodash')
, util = require('util') , util = require('util')
, Dottie = require('dottie'); , Dottie = require('dottie')
, uuid = require('node-uuid');
module.exports = (function() { module.exports = (function() {
var QueryGenerator = { var QueryGenerator = {
...@@ -212,7 +213,7 @@ module.exports = (function() { ...@@ -212,7 +213,7 @@ module.exports = (function() {
//valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc() RETURNS SETOF <%= table %> AS $body$ BEGIN RETURN QUERY ' + valueQuery + '; EXCEPTION ' + options.exception + ' END; $body$ LANGUAGE plpgsql; SELECT * FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();'; //valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc() RETURNS SETOF <%= table %> AS $body$ BEGIN RETURN QUERY ' + valueQuery + '; EXCEPTION ' + options.exception + ' END; $body$ LANGUAGE plpgsql; SELECT * FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();';
// >= 9.2 - Use a UUID but prefix with 'func_' (numbers first not allowed) // >= 9.2 - Use a UUID but prefix with 'func_' (numbers first not allowed)
var delimiter = '$func_' + Utils.generateUUID().replace(/-/g, '') + '$'; var delimiter = '$func_' + uuid.v4().replace(/-/g, '') + '$';
options.exception = 'WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL;'; options.exception = 'WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL;';
valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response <%= table %>, OUT sequelize_caught_exception text) RETURNS RECORD AS ' + delimiter + valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response <%= table %>, OUT sequelize_caught_exception text) RETURNS RECORD AS ' + delimiter +
......
...@@ -576,14 +576,15 @@ module.exports = (function() { ...@@ -576,14 +576,15 @@ module.exports = (function() {
var values = Utils.mapValueFieldNames(this.dataValues, options.fields, this.Model) var values = Utils.mapValueFieldNames(this.dataValues, options.fields, this.Model)
, query = null , query = null
, args = []; , args = []
, now = Utils.now(this.sequelize.options.dialect);
if (updatedAtAttr && !options.silent) { if (updatedAtAttr && !options.silent) {
self.dataValues[updatedAtAttr] = values[self.Model.rawAttributes[updatedAtAttr].field || updatedAtAttr] = self.Model.__getTimestamp(updatedAtAttr); self.dataValues[updatedAtAttr] = values[self.Model.rawAttributes[updatedAtAttr].field || updatedAtAttr] = self.Model.$getDefaultTimestamp(updatedAtAttr) || now;
} }
if (self.isNewRecord && createdAtAttr && !values[createdAtAttr]) { if (self.isNewRecord && createdAtAttr && !values[createdAtAttr]) {
self.dataValues[createdAtAttr] = values[self.Model.rawAttributes[createdAtAttr].field || createdAtAttr] = self.Model.__getTimestamp(createdAtAttr); self.dataValues[createdAtAttr] = values[self.Model.rawAttributes[createdAtAttr].field || createdAtAttr] = self.Model.$getDefaultTimestamp(createdAtAttr) || now;
} }
if (self.isNewRecord) { if (self.isNewRecord) {
...@@ -881,7 +882,7 @@ module.exports = (function() { ...@@ -881,7 +882,7 @@ module.exports = (function() {
} }
if (updatedAtAttr && !values[updatedAtAttr]) { if (updatedAtAttr && !values[updatedAtAttr]) {
options.attributes[updatedAtAttr] = this.Model.__getTimestamp(updatedAtAttr); options.attributes[updatedAtAttr] = this.Model.$getDefaultTimestamp(updatedAtAttr) || Utils.now(this.sequelize.options.dialect);
} }
Object.keys(values).forEach(function(attr) { Object.keys(values).forEach(function(attr) {
......
...@@ -327,7 +327,7 @@ module.exports = (function() { ...@@ -327,7 +327,7 @@ module.exports = (function() {
if (definition.hasOwnProperty('defaultValue')) { if (definition.hasOwnProperty('defaultValue')) {
if (typeof definition.defaultValue === 'function' && ( if (typeof definition.defaultValue === 'function' && (
definition.defaultValue === DataTypes.NOW || definition.defaultValue === DataTypes.NOW ||
definition.defaultValue === DataTypes.UUIDV4 || definition.defaultValue === DataTypes.UUIDV1 ||
definition.defaultValue === DataTypes.UUIDV4 definition.defaultValue === DataTypes.UUIDV4
)) { )) {
definition.defaultValue = new definition.defaultValue(); definition.defaultValue = new definition.defaultValue();
...@@ -1257,11 +1257,13 @@ module.exports = (function() { ...@@ -1257,11 +1257,13 @@ module.exports = (function() {
// Map field names // Map field names
values = Utils.mapValueFieldNames(instance.dataValues, options.fields, this); values = Utils.mapValueFieldNames(instance.dataValues, options.fields, this);
var now = Utils.now(this.sequelize.options.dialect);
if (createdAtAttr && !values[createdAtAttr]) { if (createdAtAttr && !values[createdAtAttr]) {
values[createdAtAttr] = this.__getTimestamp(createdAtAttr); values[createdAtAttr] = this.$getDefaultTimestamp(createdAtAttr) || now;
} }
if (updatedAtAttr && !values[updatedAtAttr]) { if (updatedAtAttr && !values[updatedAtAttr]) {
values[updatedAtAttr] = this.__getTimestamp(updatedAtAttr); values[updatedAtAttr] = this.$getDefaultTimestamp(updatedAtAttr) || now;
} }
// Build adds a null value for the primary key, if none was given by the user. // Build adds a null value for the primary key, if none was given by the user.
...@@ -1633,7 +1635,7 @@ module.exports = (function() { ...@@ -1633,7 +1635,7 @@ module.exports = (function() {
} }
if (this._timestampAttributes.updatedAt) { if (this._timestampAttributes.updatedAt) {
values[this._timestampAttributes.updatedAt] = this.__getTimestamp(this._timestampAttributes.updatedAt); values[this._timestampAttributes.updatedAt] = this.$getDefaultTimestamp(this._timestampAttributes.updatedAt) || Utils.now(this.sequelize.options.dialect);
} }
var instances var instances
...@@ -1789,12 +1791,11 @@ module.exports = (function() { ...@@ -1789,12 +1791,11 @@ module.exports = (function() {
return this.QueryInterface.describeTable(this.tableName, schema || this.options.schema || undefined); return this.QueryInterface.describeTable(this.tableName, schema || this.options.schema || undefined);
}; };
Model.prototype.__getTimestamp = function(attr) { Model.prototype.$getDefaultTimestamp = function(attr) {
if (!!this.rawAttributes[attr] && !!this.rawAttributes[attr].defaultValue) { if (!!this.rawAttributes[attr] && !!this.rawAttributes[attr].defaultValue) {
return Utils.toDefaultValue(this.rawAttributes[attr].defaultValue); return Utils.toDefaultValue(this.rawAttributes[attr].defaultValue);
} else {
return Utils.now(this.sequelize.options.dialect);
} }
return undefined;
}; };
// Inject current scope into options. Includes should have been conformed (conformOptions) before calling this // Inject current scope into options. Includes should have been conformed (conformOptions) before calling this
......
'use strict'; 'use strict';
var Utils = require('./utils'); var Utils = require('./utils')
, uuid = require('node-uuid');
/** /**
* The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`. * The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`.
...@@ -22,7 +23,7 @@ var Transaction = module.exports = function(sequelize, options) { ...@@ -22,7 +23,7 @@ var Transaction = module.exports = function(sequelize, options) {
autocommit: true, autocommit: true,
isolationLevel: sequelize.options.isolationLevel isolationLevel: sequelize.options.isolationLevel
}, options || {}); }, options || {});
this.id = this.options.transaction ? this.options.transaction.id : Utils.generateUUID(); this.id = this.options.transaction ? this.options.transaction.id : uuid.v4();
if (this.options.transaction) { if (this.options.transaction) {
this.id = this.options.transaction.id; this.id = this.options.transaction.id;
...@@ -30,7 +31,7 @@ var Transaction = module.exports = function(sequelize, options) { ...@@ -30,7 +31,7 @@ var Transaction = module.exports = function(sequelize, options) {
this.name = this.id + '-savepoint-' + this.options.transaction.savepoints.length; this.name = this.id + '-savepoint-' + this.options.transaction.savepoints.length;
this.parent = this.options.transaction; this.parent = this.options.transaction;
} else { } else {
this.id = this.name = Utils.generateUUID(); this.id = this.name = uuid.v4();
} }
}; };
......
...@@ -5,7 +5,6 @@ var DataTypes = require('./data-types') ...@@ -5,7 +5,6 @@ var DataTypes = require('./data-types')
, lodash = require('lodash') , lodash = require('lodash')
, ParameterValidator = require('./utils/parameter-validator') , ParameterValidator = require('./utils/parameter-validator')
, inflection = require('inflection') , inflection = require('inflection')
, _ = require('lodash')
, dottie = require('dottie') , dottie = require('dottie')
, uuid = require('node-uuid') , uuid = require('node-uuid')
, deprecate = require('depd')('Utils'); , deprecate = require('depd')('Utils');
...@@ -139,7 +138,7 @@ var Utils = module.exports = { ...@@ -139,7 +138,7 @@ var Utils = module.exports = {
delete attributes[attribute]; delete attributes[attribute];
} }
if (_.isPlainObject(attributes[attribute])) { if (lodash.isPlainObject(attributes[attribute])) {
attributes[attribute] = Utils.mapOptionFieldNames({ attributes[attribute] = Utils.mapOptionFieldNames({
where: attributes[attribute] where: attributes[attribute]
}, Model).where; }, Model).where;
...@@ -220,8 +219,13 @@ var Utils = module.exports = { ...@@ -220,8 +219,13 @@ var Utils = module.exports = {
}, },
toDefaultValue: function(value) { toDefaultValue: function(value) {
if (lodash.isFunction(value)) { if (typeof value === 'function') {
return value(); var tmp = value();
if (tmp instanceof DataTypes.ABSTRACT) {
return tmp.toSql();
} else {
return tmp;
}
} else if (value instanceof DataTypes.UUIDV1) { } else if (value instanceof DataTypes.UUIDV1) {
return uuid.v1(); return uuid.v1();
} else if (value instanceof DataTypes.UUIDV4) { } else if (value instanceof DataTypes.UUIDV4) {
...@@ -392,19 +396,12 @@ var Utils = module.exports = { ...@@ -392,19 +396,12 @@ var Utils = module.exports = {
this.logic = logic; this.logic = logic;
}, },
generateUUID: function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
validateParameter: function(value, expectation, options) { validateParameter: function(value, expectation, options) {
return ParameterValidator.check(value, expectation, options); return ParameterValidator.check(value, expectation, options);
}, },
formatReferences: function (obj) { formatReferences: function (obj) {
if (!_.isPlainObject(obj.references)) { if (!lodash.isPlainObject(obj.references)) {
deprecate('Non-object references property found. Support for that will be removed in version 4. Expected { references: { model: "value", key: "key" } } instead of { references: "value", referencesKey: "key" }.'); deprecate('Non-object references property found. Support for that will be removed in version 4. Expected { references: { model: "value", key: "key" } } instead of { references: "value", referencesKey: "key" }.');
obj.references = { model: obj.references, key: obj.referencesKey, deferrable: obj.referencesDeferrable }; obj.references = { model: obj.references, key: obj.referencesKey, deferrable: obj.referencesDeferrable };
obj.referencesKey = undefined; obj.referencesKey = undefined;
......
...@@ -88,6 +88,14 @@ suite(Support.getTestDialectTeaser('SQL'), function() { ...@@ -88,6 +88,14 @@ suite(Support.getTestDialectTeaser('SQL'), function() {
mysql: 'CHAR(36) BINARY', mysql: 'CHAR(36) BINARY',
sqlite: 'UUID' sqlite: 'UUID'
}); });
testsql('UUIDV1', DataTypes.UUIDV1, {
default: 'UUIDV1'
});
testsql('UUIDV4', DataTypes.UUIDV4, {
default: 'UUIDV4'
});
}); });
suite('NOW', function () { suite('NOW', function () {
......
...@@ -9,6 +9,28 @@ var chai = require('chai') ...@@ -9,6 +9,28 @@ var chai = require('chai')
// Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation // Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation
suite(Support.getTestDialectTeaser('Utils'), function() { suite(Support.getTestDialectTeaser('Utils'), function() {
suite('toDefaultValue', function () {
test('return plain data types', function () {
expect(Utils.toDefaultValue(DataTypes.UUIDV4)).to.equal('UUIDV4');
});
test('return uuid v1', function () {
expect(/^[a-z0-9\-]{36}$/.test(Utils.toDefaultValue(DataTypes.UUIDV1()))).to.be.equal(true);
});
test('return uuid v4', function () {
expect(/^[a-z0-9\-]{36}/.test(Utils.toDefaultValue(DataTypes.UUIDV4()))).to.be.equal(true);
});
test('return now', function () {
expect(Object.prototype.toString.call(Utils.toDefaultValue(DataTypes.NOW()))).to.be.equal('[object Date]');
});
test('return plain string', function () {
expect(Utils.toDefaultValue('Test')).to.equal('Test');
});
test('return plain object', function () {
chai.assert.deepEqual({}, Utils.toDefaultValue({}));
});
});
suite('mapOptionFieldNames', function () { suite('mapOptionFieldNames', function () {
test('plain where', function () { test('plain where', function () {
expect(Utils.mapOptionFieldNames({ expect(Utils.mapOptionFieldNames({
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!