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

Commit 0b090296 by Daniel Durante

Merge branch 'master' into milestones/2.0.0

2 parents 11c875e0 abd0f717
......@@ -77,16 +77,15 @@ var createMigrationsFolder = function(force) {
var readConfig = function() {
var config
try {
config = fs.readFileSync(configuration.configFile)
config = require(configuration.configFile);
} catch(e) {
throw new Error('Error reading "' + relativeConfigFile() + '".')
}
try {
config = JSON.parse(config)
} catch (e) {
throw new Error('Error parsing "' + relativeConfigFile() + '" as JSON.')
if(typeof config != 'object') {
throw new Error('Config must be an object: ' + relativeConfigFile());
}
console.log('Loaded configuration file "' + relativeConfigFile() + '".')
if (config[configuration.environment]) {
console.log('Using environment "' + configuration.environment + '".')
......
......@@ -42,7 +42,6 @@
- [BUG] Added tests & bugfixes for DAO-Factory.update and array of values in where clause [#880](https://github.com/sequelize/sequelize/pull/880). thanks to domasx2
- [BUG] sqlite no longer leaks a global `db` variable [#900](https://github.com/sequelize/sequelize/pull/900). thanks to xming
- [BUG] Fix for counts queries with no result [#906](https://github.com/sequelize/sequelize/pull/906). thanks to iamjochem
- [BUG] Allow include when the same table is referenced multiple times using hasMany [#913](https://github.com/sequelize/sequelize/pull/913). thanks to janmeier
- [FEATURE] Validate a model before it gets saved. [#601](https://github.com/sequelize/sequelize/pull/601). thanks to durango
- [FEATURE] Schematics. [#564](https://github.com/sequelize/sequelize/pull/564). thanks to durango
- [FEATURE] Foreign key constraints. [#595](https://github.com/sequelize/sequelize/pull/595). thanks to optilude
......@@ -76,6 +75,8 @@
- [FEATURE] Added Sequelize.fn() and Sequelize.col() to properly call columns and functions within Sequelize. [#882](https://github.com/sequelize/sequelize/pull/882). thanks to janmeier
- [FEATURE] Sequelize.import supports relative paths. [#901](https://github.com/sequelize/sequelize/pull/901). thanks to accerqueira.
- [FEATURE] Sequelize.import can now handle functions. [#911](https://github.com/sequelize/sequelize/pull/911). Thanks to davidrivera.
- [BUG] Allow include when the same table is referenced multiple times using hasMany [#913](https://github.com/sequelize/sequelize/pull/913). thanks to janmeier
- [FEATURE] Uses sequelize.fn and sequelize.col functionality to allow you to use the value of another column or a function when updating. It also allows you to use a function as a default value when supported (in sqlite and postgres). [#928](https://github.com/sequelize/sequelize/pull/928). thanks to janmeier
- [REFACTORING] hasMany now uses a single SQL statement when creating and destroying associations, instead of removing each association seperately [690](https://github.com/sequelize/sequelize/pull/690). Inspired by [#104](https://github.com/sequelize/sequelize/issues/104). janmeier
- [REFACTORING] Consistent handling of offset across dialects. Offset is now always applied, and limit is set to max table size of not limit is given [#725](https://github.com/sequelize/sequelize/pull/725). janmeier
- [REFACTORING] Moved Jasmine to Buster and then Buster to Mocha + Chai. sdepold and durango
......
var Utils = require("../../utils")
, SqlString = require("../../sql-string")
module.exports = (function() {
var QueryGenerator = {
......@@ -318,8 +319,12 @@ module.exports = (function() {
/*
Escape a value (e.g. a string, number or date)
*/
escape: function(value) {
throwMethodUndefined('escape')
escape: function(value, field) {
if (value instanceof Utils.fn || value instanceof Utils.col) {
return value.toString(this)
} else {
return SqlString.escape(value, false, null, this.dialect, field)
}
}
}
......
......@@ -605,12 +605,7 @@ module.exports = (function() {
quoteIdentifiers: function(identifiers, force) {
return identifiers.split('.').map(function(v) { return this.quoteIdentifier(v, force) }.bind(this)).join('.')
},
escape: function(value) {
return SqlString.escape(value, false, null, "mysql")
}
}
return Utils._.extend(Utils._.clone(require("../abstract/query-generator")), QueryGenerator)
......
......@@ -858,12 +858,7 @@ module.exports = (function() {
quoteIdentifiers: function(identifiers, force) {
return identifiers.split('.').map(function(t) { return this.quoteIdentifier(t, force) }.bind(this)).join('.')
},
escape: function(value, field) {
return SqlString.escape(value, false, null, "postgres", field)
}
}
// Private
......
......@@ -486,12 +486,7 @@ module.exports = (function() {
quoteIdentifiers: function(identifiers, force) {
return identifiers.split('.').map(function(v) { return this.quoteIdentifier(v, force) }.bind(this)).join('.')
},
escape: function(value) {
return SqlString.escape(value, false, null, "sqlite")
}
}
return Utils._.extend({}, MySqlQueryGenerator, QueryGenerator)
......
......@@ -74,7 +74,7 @@
"sequelize": "bin/sequelize"
},
"engines": {
"node": ">=0.4.6"
"node": ">=0.6.21"
},
"license": "MIT"
}
......@@ -333,6 +333,68 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
})
describe('create', function() {
it('is possible to use funtions when creating an instance', function (done) {
var self = this
this.User.create({
secretValue: this.sequelize.fn('upper', 'sequelize')
}).success(function (user) {
self.User.find(user.id).success(function (user) {
expect(user.secretValue).to.equal('SEQUELIZE')
done()
})
})
})
it('is possible to use functions as default values', function (done) {
var self = this
, userWithDefaults
if (dialect.indexOf('postgres') === 0) {
this.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"').success(function() {
userWithDefaults = self.sequelize.define('userWithDefaults', {
uuid: {
type: 'UUID',
defaultValue: self.sequelize.fn('uuid_generate_v4')
}
})
userWithDefaults.sync({force: true}).success(function () {
userWithDefaults.create({}).success(function (user) {
// uuid validation regex taken from http://stackoverflow.com/a/13653180/800016
expect(user.uuid).to.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)
done()
})
})
})
} else if (dialect === 'sqlite') {
// The definition here is a bit hacky. sqlite expects () around the expression for default values, so we call a function without a name
// to enclose the date function in (). http://www.sqlite.org/syntaxdiagrams.html#column-constraint
userWithDefaults = self.sequelize.define('userWithDefaults', {
year: {
type: Sequelize.STRING,
defaultValue: self.sequelize.fn('', self.sequelize.fn('date', 'now'))
}
})
userWithDefaults.sync({force: true}).success(function () {
userWithDefaults.create({}).success(function (user) {
userWithDefaults.find(user.id).success(function (user) {
var now = new Date()
, pad = function (number) {
if (number > 9) {
return number
}
return '0' + number
}
expect(user.year).to.equal(now.getFullYear() + '-' + pad(now.getMonth() + 1) + '-' + pad(now.getDate()))
done()
})
})
})
} else {
// functions as default values are not supported in mysql, see http://stackoverflow.com/a/270338/800016
done()
}
})
it("casts empty arrays correctly for postgresql insert", function(done) {
if (dialect !== "postgres" && dialect !== "postgresql-native") {
expect('').to.equal('')
......@@ -955,6 +1017,21 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
})
})
it('updates with function and column value', function (done) {
var self = this
this.User.create({
username: 'John'
}).success(function(user) {
self.User.update({username: self.sequelize.fn('upper', self.sequelize.col('username'))}, {username: 'John'}).success(function () {
self.User.all().success(function(users) {
expect(users[0].username).to.equal('JOHN')
done()
})
})
})
})
it('sets updatedAt to the current timestamp', function(done) {
var self = this
, data = [{ username: 'Peter', secretValue: '42' },
......
......@@ -641,6 +641,25 @@ describe(Support.getTestDialectTeaser("DAO"), function () {
}, 1000)
})
it('updates with function and column value', function (done) {
var self = this
this.User.create({
aNumber: 42
}).success(function(user) {
user.bNumber = self.sequelize.col('aNumber')
user.username = self.sequelize.fn('upper', 'sequelize')
user.save().success(function(){
self.User.find(user.id).success(function(user2) {
expect(user2.username).to.equal('SEQUELIZE')
expect(user2.bNumber).to.equal(42)
done()
})
})
})
})
describe('without timestamps option', function() {
it("doesn't update the updatedAt column", function(done) {
var User2 = this.sequelize.define('User2', {
......
......@@ -308,6 +308,14 @@ if (dialect.match(/^mysql/)) {
}, {
arguments: ['myTable', {foo: true}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (true);"
}, {
arguments: ['myTable', function (sequelize) {
return {
foo: sequelize.fn('NOW')
}
}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (NOW());",
needsSequelize: true
}
],
......@@ -375,6 +383,22 @@ if (dialect.match(/^mysql/)) {
}, {
arguments: ['myTable', {bar: true}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=true WHERE `name`='foo'"
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.fn('NOW')
}
}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=NOW() WHERE `name`='foo'",
needsSequelize: true
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.col('foo')
}
}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=`foo` WHERE `name`='foo'",
needsSequelize: true
}
],
......
......@@ -451,6 +451,14 @@ if (dialect.match(/^postgres/)) {
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;"
}, {
arguments: ['myTable', function (sequelize) {
return {
foo: sequelize.fn('NOW')
}
}],
expectation: "INSERT INTO \"myTable\" (\"foo\") VALUES (NOW()) RETURNING *;",
needsSequelize: true
},
// Variants when quoteIdentifiers is false
......@@ -630,6 +638,22 @@ if (dialect.match(/^postgres/)) {
}, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *"
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.fn('NOW')
}
}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=NOW() WHERE \"name\"='foo' RETURNING *",
needsSequelize: true
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.col('foo')
}
}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=\"foo\" WHERE \"name\"='foo' RETURNING *",
needsSequelize: true
},
// Variants when quoteIdentifiers is false
......
......@@ -294,6 +294,14 @@ if (dialect === 'sqlite') {
arguments: ['myTable', {name: 'foo', foo: 1, nullValue: undefined}],
expectation: "INSERT INTO `myTable` (`name`,`foo`) VALUES ('foo',1);",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', function (sequelize) {
return {
foo: sequelize.fn('NOW')
}
}],
expectation: "INSERT INTO `myTable` (`foo`) VALUES (NOW());",
needsSequelize: true
}
],
......@@ -373,6 +381,22 @@ if (dialect === 'sqlite') {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=2 WHERE `name`='foo'",
context: {options: {omitNull: true}}
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.fn('NOW')
}
}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=NOW() WHERE `name`='foo'",
needsSequelize: true
}, {
arguments: ['myTable', function (sequelize) {
return {
bar: sequelize.col('foo')
}
}, {name: 'foo'}],
expectation: "UPDATE `myTable` SET `bar`=`foo` WHERE `name`='foo'",
needsSequelize: true
}
],
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!