Skip to content

Instantly share code, notes, and snippets.

@myndzi
Created September 10, 2014 01:40
Show Gist options
  • Save myndzi/7035b05902d226a1fc8e to your computer and use it in GitHub Desktop.
Save myndzi/7035b05902d226a1fc8e to your computer and use it in GitHub Desktop.
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