@@ -14,7 +14,13 @@ Sequelize is a promise-based Node.js/io.js ORM for Postgres, MySQL, MariaDB, SQL
From 3.0.0 and up Sequelize will follow SEMVER.
[Upgrading to 2.0](https://github.com/sequelize/sequelize/wiki/Upgrading-to-2.0)
## Backwards compatibility changes
3.0.0 cleans up a lot of deprecated code, making it easier for us to develop and maintain features in the future. This implies that most of the changes in 3.0.0 are breaking changes! Please read the changelog for 3.0.0 carefully.
[Upgrading to 3.0](https://github.com/sequelize/sequelize/wiki/Upgrading-to-3.0).
We highly recommend to use 3.0 as it also includes security related fixes that can't be backported to either 2.0 or 1.7.
If you still use 1.7 please read our guide [Upgrading to 2.0](https://github.com/sequelize/sequelize/wiki/Upgrading-to-2.0) plus the changelog up to now. Version 2.1 also contained new breaking changes.
3.0.0 cleans up a lot of deprecated code, making it easier for us to develop and maintain features in the future.
-[ADDED] findById/findByPrimary takes a single value as argument representing the primary key to find.
-[ADDED] findById / findByPrimary takes a single value as argument representing the primary key to find.
-[CHANGED] belongsToMany relations MUST now be given a `through` argument.
-[CHANGED] findOne/findAll/findAndCount/findOrCreate now only takes a single options argument instead of a options, queryOptions argument. So set transaction, raw, etc on the first options argument.
-[CHANGED] findOne / findAll / findAndCount / findOrCreate now only takes a single options argument instead of a options and queryOptions argument. So set transaction, raw, etc on the first options argument.
-[CHANGED] The accessor for belongsToMany relationships is now either the `as` argument or the target model name pluralized.
-[REMOVED] N:M relationships can no longer be represented by 2 x hasMany
-[REMOVED] Model.create/Model.bulkCreate no longer takes an array of fields as its second argument, use `options.fields` instead.
-[REMOVED] Query Chainer has been remved
-[REMOVED] Model.create / Model.bulkCreate / Instance.save no longer takes an array of fields as its second argument, use `options.fields` instead.
-[REMOVED] Query Chainer has been removed
-[REMOVED] Migrations have been removed, use umzug instead
-[REMOVED] Model.findAllJoin has been removed
-[REMOVED] sequelize.query now only takes `sql, callee, options` as arguments, the 4th argument `replacements` has been removed and should be set via`options.replacements` instead.
-[REMOVED] sequelize.query now only takes `sql and options` as arguments, the second and fourth argument `callee` and `replacements` have been removed and should be set via `options.instance` / `options.model` and `options.replacements` instead.
-[REMOVED]`instance.isDirty` has been removed, use `instance.changed()` instead
-[REMOVED]`instance.values` has been removed, use `instance.get()` instead
-[REMOVED]`instance.primaryKeyValues` has been removed.
-[REMOVED]`instance.identifiers` has been removed, use `instance.where()` instead
-[REMOVED]`instance.isDeleted` has been removed, simply check the timestamp with `get('deletedAt')` instead
-[REMOVED]`instance.increment/decrement` now longer takes a number as it's second argument.
-[REMOVED/SECURITY] findOne no longer takes a string/integer/binary argument to represent a primaryKey. Use findById instead
-[REMOVED/SECURITY] findOne no longer takes a string / integer / binary argument to represent a primaryKey. Use findById instead
-[REMOVED/SECURITY]`where: "raw query"` is no longer legal, you must now explicitely use `where: ["raw query", [replacements]]`
-[BUG] Fix showIndexQuery so appropriate indexes are returned when a schema is used
-[BUG] Fix addIndexQuery error when the model has a schema
...
...
@@ -25,6 +26,7 @@
-[BUG] Fix bulkCreate: do not insert NULL for undefined values [3729](https://github.com/sequelize/sequelize/pull/3729)
-[BUG] Fix trying to roll back a comitted transaction if an error occured while comitting resulting in an unhandled rejection [3726](https://github.com/sequelize/sequelize/pull/3726)
-[BUG] Fix regression in beforeUpdate hook where `instance.changed()` would always be false [3727](https://github.com/sequelize/sequelize/pull/3727)
-[BUG] Fix trying to roll back a comitted transaction if an error occured while comitting
#### Backwards compatibility changes
- Most of the changes in 3.0.0 are BC breaking, read the changelog for 3.0.0 carefully.
@@ -144,13 +144,13 @@ Defining `through` is required. Sequelize would previously attempt to autogenera
This will add methods `getUsers`, `setUsers`, `addUsers` to `Project`, and `getProjects`, `setProjects` and `addProject` to `User`.
Sometimes you may want to rename your models when using them in associations. Let's define users as workers and projects as tasks by using the alias (`as`) option:
To add a new project to a user and set it's status, you pass an extra object to the setter, which contains the attributes for the join table
```js
user.addProject(project,{status:'started'})
```
By default the code above will add ProjectId and UserId to the UserProjects table, and _remove any previously defined primary key attribute_ - the table will be uniquely identified by the combination of the keys of the two tables, and there is no reason to have other PK columns. To enforce a primary key on the `UserProjects` model you can add it manually.
The relation between task and user injects the `user_id` foreign key on tasks, and marks it as a reference to the `User` table. By default `user_id` will be set to `NULL` if the referenced user is deleted, and updated if the id of the user id updated. These options can be overridden by passing `onUpdate` and `onDelete` options to the association calls. The validation options are `RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL`.
The relation between task and user injects the `user_id` foreign key on tasks, and marks it as a reference to the `User` table. By default `user_id` will be set to `NULL` if the referenced user is deleted, and updated if the id of the user id updated. These options can be overridden by passing `onUpdate` and `onDelete` options to the association calls. The validation options are `RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL`.
For 1:1 and 1:m associations the default option is `SET NULL` for deletion, and `CASCADE` for updates. For n:m, the default for both is `CASCADE`. This means, that if you delete or update a row from one side of an n:m association, all the rows in the join table referencing that row will also be deleted or updated.
Adding constraints between tables means that tables must be created in the database in a certain order, when using `sequelize.sync`. If Task has a reference to User, the User table must be created before the Task table can be created. This can sometimes lead to circular references, where sequelize cannot find an order in which to sync. Imagine a scenario of documents and versions. A document can have multiple versions, and for convenience, a document has an reference to it's current version.
```js
varDocument=this.sequelize.define('Document',{
author:Sequelize.STRING
...
...
@@ -547,29 +547,29 @@ var Document = this.sequelize.define('Document', {
,Version=this.sequelize.define('Version',{
timestamp:Sequelize.DATE
})
Document.hasMany(Version)// This adds document_id to version
Document.belongsTo(Version,{as:'Current',foreignKey:'current_version_id'})// This adds current_version_id to document
```
However, the code above will result in the following error: `Cyclic dependency found. 'Document' is dependent of itself. Dependency Chain: Document -> Version => Document`. In order to alleviate that, we can pass `constraints: false` to one of the associations:
@@ -577,7 +577,7 @@ CREATE TABLE IF NOT EXISTS `Version` (
### Enforcing a foreign key reference without constraints
Some times you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition, and mark the relations between them.
@@ -2,32 +2,32 @@ Hooks (also known as callbacks or lifecycle events), are functions which are cal
## Order of Operations
```
(1)
beforeBulkCreate(instances, options, fn)
beforeBulkDestroy(instances, options, fn)
```
(1)
beforeBulkCreate(instances, options, fn)
beforeBulkDestroy(instances, options, fn)
beforeBulkUpdate(instances, options, fn)
(2)
(2)
beforeValidate(instance, options, fn)
(-)
validate
(3)
(3)
afterValidate(instance, options, fn)
(4)
(4)
beforeCreate(instance, options, fn)
beforeDestroy(instance, options, fn)
beforeUpdate(instance, options, fn)
(-)
create
destroy
(-)
create
destroy
update
(5)
afterCreate(instance, options, fn)
(5)
afterCreate(instance, options, fn)
afterDestroy(instance, options, fn)
afterUpdate(instance, options, fn)
(6)
afterBulkCreate(instances, options, fn)
afterBulkDestory(instances, options, fn)
afterUpdate(instance, options, fn)
(6)
afterBulkCreate(instances, options, fn)
afterBulkDestory(instances, options, fn)
afterBulkUpdate(instances, options, fn)
```
...
...
@@ -35,7 +35,7 @@ Hooks (also known as callbacks or lifecycle events), are functions which are cal
There are currently three ways to programmatically add hooks. A hook function always runs asynchronousĺy, and can be resolved either by calling a callback (passed as the last argument),
or by returning a promise.
```js
// Method 1 via the .define() method
varUser=sequelize.define('User',{
...
...
@@ -56,7 +56,7 @@ var User = sequelize.define('User', {
}
}
})
// Method 2 via the .hook() method
varUser=sequelize.define('User',{
username:DataTypes.STRING,
...
...
@@ -65,16 +65,16 @@ var User = sequelize.define('User', {
Sometimes you'll be editing more than one record at a time by utilizing the `bulkCreate, update, destroy` methods on the model. The following will emit whenever you're using one of those methods.
Note that many model operations in Sequelize allow you to specify a transaction in the options parameter of the method. If a transaction _is_ specified in the original call, it will be present in the options parameter passed to the hook function. For example, consider the following snippet:
```js
// Here we use the promise-style of async hooks rather than
// the callback.
User.hook('afterCreate',function(user,options){
// 'transaction' will be available in options.transaction
// This operation will be part of the same transaction as the
// This operation will be part of the same transaction as the
If we had not included the transaction option in our call to `User.update` in the preceding code, no change would have occurred, since our newly created user does not exist in the database until the pending transaction has been committed.
If we had not included the transaction option in our call to `User.update` in the preceding code, no change would have occurred, since our newly created user does not exist in the database until the pending transaction has been committed.
In order to create instances of defined classes just do as follows. You might recognize the syntax if you coded Ruby in the past. Using the `build`-method will return an unsaved object, which you explicitly have to save.
```js
varproject=Project.build({
title:'my awesome project',
...
...
@@ -56,7 +56,7 @@ Task
## Creating persistent instances
Besides constructing objects, that needs an explicit save call to get stored in the database, there is also the possibility to do all those steps with one single command. It's called `create`.
It is also possible to define which attributes can be set via the create method. This can be especially very handy if you create database entries based on a form which can be filled by a user. Using that would for example allow you to restrict the `User` model to set only a username and an address but not an admin flag:
Now lets change some values and save changes to the database... There are two ways to do that:
```js
// way 1
task.title='a very different title now'
...
...
@@ -90,7 +90,7 @@ task.updateAttributes({
```
It's also possible to define which attributes should be saved when calling `save`, by passing an array of column names. This is useful when you set attributes based on a previously defined object. E.g. if you get the values of an object via a form of a web app. Furthermore this is used internally for `updateAttributes`. This is how it looks like:
```js
task.title='foooo'
task.description='baaaaaar'
...
...
@@ -119,7 +119,7 @@ Task.create({ title: 'a task' }).then(function(task) {
```
If the `paranoid` options is true, the object will not be deleted, instead the `deletedAt` column will be set to the current timestamp. To force the deletion, you can pass `force: true` to the destroy call:
```js
task.destroy({force:true})
```
...
...
@@ -135,7 +135,7 @@ In addition to updating a single instance, you can also create, update, and dele
Since you are working with multiple models, the callbacks will not return DAO instances. BulkCreate will return an array of model instances/DAOs, they will however, unlike `create`, not have the resulting values of autoIncrement attributes.`update` and `destroy` will return the number of affected rows.
First lets look at bulkCreate
```js
User.bulkCreate([
{username:'barfooz',isAdmin:true},
...
...
@@ -149,7 +149,7 @@ User.bulkCreate([
```
To update several rows at once:
```js
Task.bulkCreate([
{subject:'programming',status:'executing'},
...
...
@@ -157,7 +157,7 @@ Task.bulkCreate([
{subject:'programming',status:'finished'}
]).then(function(){
Task.update(
{status:'inactive'}/* set attributes' value */,
{status:'inactive'}/* set attributes' value */,
{where:{subject:'programming'}}/* where criteria */
).then(function(affectedRows){
// affectedRows will be 2
...
...
@@ -169,14 +169,14 @@ Task.bulkCreate([
```
And delete them:
```js
Task.bulkCreate([
{subject:'programming',status:'executing'},
{subject:'reading',status:'executing'},
{subject:'programming',status:'finished'}
]).then(function(){
Task.destroy({
Task.destroy({
where:{
subject:'programming'
},
...
...
@@ -191,18 +191,18 @@ Task.bulkCreate([
```
If you are accepting values directly from the user, it might be beneficial to limit the columns that you want to actually insert.`bulkCreate()`accepts an options object as the second parameter. The object can have a `fields` parameter, (an array) to let it know which fields you want to build explicitly
```js
User.bulkCreate([
{username:'foo'},
{username:'bar',admin:true}
],{fields:['username']}).then(function(){
// nope bar, you can't be admin!
// nope bar, you can't be admin!
})
```
`bulkCreate` was originally made to be a mainstream/fast way of inserting records, however, sometimes you want the luxury of being able to insert multiple rows at once without sacrificing model validations even when you explicitly tell Sequelize which columns to sift through. You can do by adding a `validate: true` property to the options object.
```js
varTasks=sequelize.define('Task',{
name:{
...
...
@@ -226,19 +226,19 @@ Tasks.bulkCreate([
],{validate:true}).catch(function(errors){
/* console.log(errors) would look like:
[
{ record:
...
errors:
{ record:
...
errors:
{ name: 'SequelizeValidationError',
message: 'Validation error',
errors: [Object] } },
{ record:
{ record:
...
errors:
errors:
{ name: 'SequelizeValidationError',
message: 'Validation error',
errors: [Object] } }
]
errors: [Object] } }
]
*/
})
```
...
...
@@ -246,7 +246,7 @@ Tasks.bulkCreate([
## Values of an instance
If you log an instance you will notice, that there is a lot of additional stuff. In order to hide such stuff and reduce it to the very interesting information, you can use the`get`-attribute. Calling it with the option `plain` = true will only return the values of an instance.
--config The path to the config file. Default: config/config.json
```
## Skeleton
The following skeleton shows a typical migration file. All migrations are expected to be located in a folder called `migrations` at the very top of the project. The sequelize binary can generate a migration skeleton. See the aboves section for more details.
```js
module.exports={
up:function(migration,DataTypes,done){
up:function(migration,DataTypes){
// logic for transforming into the new state
done()// sets the migration as finished
},
down:function(migration,DataTypes,done){
down:function(migration,DataTypes){
// logic for reverting the changes
done()// sets the migration as finished
}
}
```
...
...
@@ -71,17 +69,8 @@ The passed `migration` object can be used to modify the database. The `Da
Sequelize.BLOB('tiny')// TINYBLOB (bytea for PostgreSQL. Other options are medium and long)
Sequelize.UUID// UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically)
In addition to the type mentioned above, integer, bigint and float also support unsigned and zerofill properties, which can be combined in any order:
In addition to the type mentioned above, integer, bigint, float and double also support unsigned and zerofill properties, which can be combined in any order:
Be aware that this does not apply for PostgreSQL!
```js
Sequelize.INTEGER.UNSIGNED// INTEGER UNSIGNED
...
...
@@ -142,7 +153,7 @@ var Employee = sequelize.define('Employee', {
type:Sequelize.STRING,
allowNull:false,
get:function(){
vartitle=this.getDataValue('title');
vartitle=this.getDataValue('title');
// 'this' allows you to access attributes of the instance
returnthis.getDataValue('name')+' ('+title+')';
},
...
...
@@ -180,7 +191,7 @@ var Foo = sequelize.define('Foo', {
@@ -8,7 +8,7 @@ sequelize.query("UPDATE users SET y = 42 WHERE x = 12").spread(function(results,
})
```
In cases where you don't need to access the metadata you can pass in a query type to tell sequelize how to format the results. For example, for a simple select query you could do:
In cases where you don't need to access the metadata you can pass in a query type to tell sequelize how to format the results. For example, for a simple select query you could do:
```js
sequelize.query("SELECT * FROM `users`",{type:sequelize.QueryTypes.SELECT})
Several other query types are available. [Peek into the source for details](https://github.com/sequelize/sequelize/blob/master/lib/query-types.js)
A second, optional, argument is the _callee_, which is a model. If you pass a model the returned data will be instances of that model.
A second option is the model. If you pass a model the returned data will be instances of that model.
```js
// Callee is the model definition. This allows you to easily map a query to a predefined model
sequelize.query('SELECT * FROM projects',Projects).then(function(projects){
sequelize.query('SELECT * FROM projects',{model:Projects}).then(function(projects){
// Each record will now be a instance of Project
})
```
...
...
@@ -35,13 +35,13 @@ Replacements in a query can be done in two different ways, either using named pa
* If an object is passed, `:key` will be replaced with the keys from that object. If the object contains keys not found in the query or vice verca, an exception will be thrown.
```js
sequelize.query('SELECT * FROM projects WHERE status = ?',
sequelize.query('SELECT * FROM projects WHERE status = ?',
@@ -108,7 +108,15 @@ var sequelize = new Sequelize('database', 'username', 'password', {
// language is used to determine how to translate words into singular or plural form based on the [lingo project](https://github.com/visionmedia/lingo)
// options are: en [default], es
language:'en'
language:'en',
// isolation level of each transaction. Defaults to REPEATABLE_READ
@@ -117,7 +125,7 @@ var sequelize = new Sequelize('database', 'username', 'password', {
## Read replication
Sequelize supports read replication, i.e. having multiple servers that you can connect to when you want to do a SELECT query. When you do read replication, you specify one or more servers to act as read replicas, and one server to act as the write master, which handles all writes and updates and propagates them to the replicas (note that the actual replication process is **not** handled by Sequelize, but should be set up in MySql).
```js
varsequelize=newSequelize('database',null,null,{
dialect:'mysql',
...
...
@@ -139,7 +147,7 @@ var sequelize = new Sequelize('database', null, null, {
If you have any general settings that apply to all replicas you do not need to provide them for each instance. In the code above, database name and port is propagated to all replicas. The same will happen for user and password, if you leave them out for any of the replicas. Each replica has the following options:`host`,`port`,`username`,`password`,`database`.
Sequelize uses a pool to manage connections to your replicas. The default options are:
```js
{
maxConnections:10,
...
...
@@ -159,7 +167,7 @@ With the release of Sequelize`1.6.0`, the library got independent from spe
### MySQL
In order to get Sequelize working nicely together with MySQL, you'll need to install`mysql@~2.5.0`or higher. Once that's done you can use it like this:
@@ -225,29 +233,29 @@ var sequelize = new Sequelize('database', 'username', 'password', {
As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can utilize the function `sequelize.query`.
* @param {Object} [options.fields] An optional array of strings, representing database columns. If fields is provided, only those columns will be validated and saved.
* @param {Boolean} [options.silent=false] If true, the updatedAt timestamp will not be updated.
* @param {Boolean} [options.validate=true] If false, validations won't be run.
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Transaction} [options.transaction]
*
* @return {Promise<this|Errors.ValidationError>}
*/
Instance.prototype.save=function(options){
if(arguments.length>1){
thrownewError('The second argument was removed in favor of the options object.');
* @param {String|Array|Object} fields If a string is provided, that column is incremented by the value of `by` given in options. If an array is provided, the same is true for each column. If and object is provided, each column is incremented by the value given.
* @param {Object} [options]
* @param {Integer} [options.by=1] The number to increment by
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {String|Array|Object} fields If a string is provided, that column is decremented by the value of `by` given in options. If an array is provided, the same is true for each column. If and object is provided, each column is decremented by the value given
* @param {Object} [options]
* @param {Integer} [options.by=1] The number to decrement by
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Boolean} [options.plain=false] Sets the query type to `SELECT` and return a single row
* @param {Object|Array} [options.replacements] Either an object of named parameter replacements in the format `:param` or an array of unnamed replacements to replace `?` in your SQL.
* @param {Boolean} [options.useMaster=false] Force the query to use the write pool, regardless of the query type.
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Instance} [options.instance] A sequelize instance used to build the return instance
* @param {Model} [options.model] A sequelize model used to build the returned model instances (used to be called callee)
*
* @return {Promise}
*
* @see {Model#build} for more information about callee.