Created
September 10, 2014 01:40
-
-
Save myndzi/7035b05902d226a1fc8e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/interface.js b/lib/interface.js | |
index 83b5c3d..a3263fc 100644 | |
--- a/lib/interface.js | |
+++ b/lib/interface.js | |
@@ -21,12 +21,6 @@ Target.prototype._formatQuery = function(sql, bindings, tz) { | |
return SqlString.format(sql, bindings, true, tz); | |
}; | |
-// Create a new instance of the `Runner`, passing in the current object. | |
-Target.prototype.then = function(onFulfilled, onRejected) { | |
- var Runner = this.client.Runner; | |
- return new Runner(this).run().then(onFulfilled, onRejected); | |
-}; | |
- | |
// Add additional "options" to the builder. Typically used for client specific | |
// items, like the `mysql` and `sqlite3` drivers. | |
Target.prototype.options = function(opts) { | |
@@ -65,14 +59,51 @@ Target.prototype.pipe = function(writable) { | |
return new Runner(this).pipe(writable); | |
}; | |
-// Creates a method which "coerces" to a promise, by calling a | |
-// "then" method on the current `Target` | |
-_.each(['bind', 'catch', 'spread', 'otherwise', 'map', 'reduce', 'tap', 'thenReturn', | |
- 'return', 'yield', 'ensure', 'nodeify', 'exec'], function(method) { | |
+// Create a new instance of the `Runner`, passing in the current object. | |
+// Run it, then attach all stored promise handlers | |
+Target.prototype.runQuery = function() { | |
+ var Runner = this.client.Runner; | |
+ var result = new Runner(this).run(); | |
+ | |
+ this._promises.forEach(function (args) { | |
+ var method = args.pop(); | |
+ result = result[method].apply(result, args); | |
+ }); | |
+ | |
+ this._promises.length = 0; | |
+ | |
+ return result; | |
+}; | |
+ | |
+// Capture promise-related method calls to kick off the query | |
+// We'll run the query next tick so as to allow continuations | |
+// of the query object even after a promise handler has been | |
+// bound. | |
+_.each(['then', 'bind', 'catch', 'spread', 'otherwise', 'map', 'reduce', | |
+ 'filter', 'tap', 'thenReturn', 'return', 'yield', 'ensure', 'nodeify', 'exec'], | |
+function(method) { | |
Target.prototype[method] = function() { | |
- var then = this.then(); | |
- return then[method].apply(then, arguments); | |
+ var self = this; | |
+ | |
+ var i = arguments.length, args = new Array(i); | |
+ while (i--) { args[i] = arguments[i]; } | |
+ | |
+ args.push(method); | |
+ | |
+ if (self._promises) { | |
+ self._promises.push(args); | |
+ return self; | |
+ } | |
+ | |
+ self._promises = [args]; | |
+ | |
+ process.nextTick(function () { | |
+ self.runQuery() | |
+ }); | |
+ | |
+ return this; | |
}; | |
}); | |
-}; | |
\ No newline at end of file | |
+ | |
+}; | |
diff --git a/test/integration/builder/additional.js b/test/integration/builder/additional.js | |
index d508701..bf56615 100644 | |
--- a/test/integration/builder/additional.js | |
+++ b/test/integration/builder/additional.js | |
@@ -233,6 +233,18 @@ module.exports = function(knex) { | |
expect(resp['count(*)']).to.equal(count); | |
}); | |
}); | |
+ | |
+ it('allows interleaving of query builder methods and promise methods', function() { | |
+ return knex.select('*') | |
+ .from('accounts') | |
+ .then(function (res) { | |
+ res.bar = true; | |
+ }) | |
+ .where('id', '=', 3) | |
+ .then(function (res) { | |
+ expect(res.bar).to.equal(true); | |
+ }); | |
+ }); | |
}); | |
diff --git a/test/integration/schema/index.js b/test/integration/schema/index.js | |
index ea3cf0c..f22f8c5 100644 | |
--- a/test/integration/schema/index.js | |
+++ b/test/integration/schema/index.js | |
@@ -3,6 +3,7 @@ | |
'use strict'; | |
var Promise = testPromise; | |
+Promise.resolve(); | |
module.exports = function(knex) { | |
@@ -11,16 +12,15 @@ module.exports = function(knex) { | |
describe('dropTable', function() { | |
it('has a dropTableIfExists method', function() { | |
- return Promise.all([ | |
- knex.schema.dropTableIfExists('test_foreign_table_two').testSql(function(tester) { | |
+ return knex.schema.dropTableIfExists('test_foreign_table_two').testSql(function(tester) { | |
tester(['sqlite3', 'postgresql'], ['drop table if exists "test_foreign_table_two"']); | |
tester('mysql', ['drop table if exists `test_foreign_table_two`']); | |
tester('oracle', [ | |
"begin execute immediate 'drop table \"test_foreign_table_two\"'; exception when others then if sqlcode != -942 then raise; end if; end;", | |
"begin execute immediate 'drop sequence \"test_foreign_table_two_seq\"'; exception when others then if sqlcode != -2289 then raise; end if; end;" | |
]); | |
- }), | |
- knex.schema.dropTableIfExists('test_table_one') | |
+ }).then(function () { | |
+ return knex.schema.dropTableIfExists('test_table_one') | |
.dropTableIfExists('catch_test') | |
.dropTableIfExists('test_table_two') | |
.dropTableIfExists('test_table_three') | |
@@ -35,8 +35,8 @@ module.exports = function(knex) { | |
.dropTableIfExists('test_default_table2') | |
.dropTableIfExists('test_default_table3') | |
.dropTableIfExists('knex_migrations') | |
- .dropTableIfExists('bool_test') | |
- ]); | |
+ .dropTableIfExists('bool_test'); | |
+ }); | |
}); | |
}); | |
diff --git a/test/unit/query/builder.js b/test/unit/query/builder.js | |
index 7267521..b48ce57 100644 | |
--- a/test/unit/query/builder.js | |
+++ b/test/unit/query/builder.js | |
@@ -2018,7 +2018,6 @@ module.exports = function(qb, clientName, aliasName) { | |
} | |
}); | |
}); | |
- | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment