From 1ba82b8363edeb8ef0bcd8a2bc50f37f983f530a Mon Sep 17 00:00:00 2001
From: Tim Griesser
-
Current Develop — @@ -1246,19 +1243,25 @@ knex('accounts').truncate()
- Transactions are an important feature of relational databases, as they allow correct recovery from failures and keep a database consistent even in cases of system failure. All queries within a transaction are executed on the same database connection, and run the entire set of queries as a single unit of work. Any failure will mean the database. + Transactions are an important feature of relational databases, as they allow correct recovery from failures and keep a database consistent even in cases of system failure. All queries within a transaction are executed on the same database connection, and run the entire set of queries as a single unit of work. Any failure will mean the database will rollback any queries executed on that connection to the pre-transaction state.
Transactions are handled by passing a handler function into knex.transaction. - The handler function accepts a single argument, the promise for committing or rolling back - the transaction. This argument is then passed into any queries which are involved in the current - transcaction, working by explicitly passing the . + The handler function accepts a single argument, the an object which may be used in two ways: + +
var Promise = require('bluebird');
+// Using trx as a query builder:
knex.transaction(function(trx) {
var books = [
@@ -1280,12 +1283,11 @@ knex.transaction(function(trx) {
}));
});
-}).then(function(inserts) {
-
+})
+.then(function(inserts) {
console.log(inserts.length + ' new books saved.');
-
-}).catch(function(error) {
-
+})
+.catch(function(error) {
// If we get here, that means that neither the 'Old Books' catalogues insert,
// nor any of the books inserts will have taken place.
console.error(error);
@@ -1293,6 +1295,51 @@ knex.transaction(function(trx) {
+And then this example:
+ +
+var Promise = require('bluebird');
+
+// Using trx as a transaction object:
+knex.transaction(function(trx) {
+
+ var books = [
+ {title: 'Canterbury Tales'},
+ {title: 'Moby Dick'},
+ {title: 'Hamlet'}
+ ];
+
+ knex.insert({name: 'Old Books'})
+ .into('catalogues')
+ .transacting(trx)
+ .then(function(row) {
+ return Promise.map(books, function(book) {
+ book.catalogue_id = row.id;
+
+ // Some validation could take place here.
+
+ return knex.insert(info).into('books').transacting(trx);
+ }));
+ })
+ .then(trx.commit)
+ .then(trx.rollback);
+})
+.then(function(inserts) {
+ console.log(inserts.length + ' new books saved.');
+})
+.catch(function(error) {
+ // If we get here, that means that neither the 'Old Books' catalogues insert,
+ // nor any of the books inserts will have taken place.
+ console.error(error);
+});
+
+
+
+ + Notice that if a promise is not returned within the handler, it is up to you to ensure trx.commit, or + trx.rollback are called, otherwise the transaction connection will hang. +
+@@ -1643,7 +1690,7 @@ knex.schema.createTable('accounts', function() { anywhere you want, and using proper bindings can ensure your values are escaped properly, preventing SQL-injection attacks.
-Raw expressions are created by using knex.raw(sql, [bindings]) and passing this as a value for any value in the query chain. @@ -1774,7 +1821,6 @@ promise.tap(doSideEffectsHere); -
map.map(mapper)
@@ -1877,7 +1923,7 @@ knex.insert(values).into('users').return({inserted: true});
Streams are a powerful way of piping data through as it comes in, rather than all at once. You can read more about streams here at substack's stream handbook. - See the following for example uses of stream & pipe. + See the following for example uses of stream & pipe. If you wish to use streams with PostgreSQL, you must also install the pg-query-stream module.
@@ -1981,6 +2027,44 @@ knex.select('*').from('users').where(knex.raw('id = ?', [1])).toString()
+ The migration CLI is stored in a separate repository and + is driven by the node-liftoff module. Running: +
+ ++$ knex init ++ +
+ will create a sample knexfile.js - the file which contains our various database configurations. Once you have a knexfile.js, + you can use the migration tool to create migration files to the specified directory (default migrations). Creating new migration + files can be achieved by running: +
+ ++$ knex migrate:make migration_name ++ +
+ Once you have the migrations in place you wish to run, you can run: +
+ ++$ knex migrate:latest ++ +
+ To update your database to the latest version. +
+ ++ A knexfile.js or knexfile.coffee generally contains all of the configuration for your database, for each environment you will be using. You may pass a --knexfile option to any of the command line statements to specify an alternate path to your knexfile. +
+ +@@ -2008,7 +2092,7 @@ knex.select('*').from('users').where(knex.raw('id = ?', [1])).toString()
- currentVersionknex.migrate.currentVersion()
+ currentVersionknex.migrate.currentVersion([config])
Retrieves and returns the current migration version, as a promise.
If there aren't any migrations run yet, returns "none" as the value for the currentVersion.
@@ -2070,7 +2154,7 @@ $ npm test