runner.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _isArray2 = require('lodash/isArray');
  4. var _isArray3 = _interopRequireDefault(_isArray2);
  5. var _assign2 = require('lodash/assign');
  6. var _assign3 = _interopRequireDefault(_assign2);
  7. var _bluebird = require('bluebird');
  8. var _bluebird2 = _interopRequireDefault(_bluebird);
  9. var _helpers = require('./helpers');
  10. var helpers = _interopRequireWildcard(_helpers);
  11. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  12. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  13. var PassThrough = void 0;
  14. // The "Runner" constructor takes a "builder" (query, schema, or raw)
  15. // and runs through each of the query statements, calling any additional
  16. // "output" method provided alongside the query and bindings.
  17. function Runner(client, builder) {
  18. this.client = client;
  19. this.builder = builder;
  20. this.queries = [];
  21. // The "connection" object is set on the runner when
  22. // "run" is called.
  23. this.connection = void 0;
  24. }
  25. (0, _assign3.default)(Runner.prototype, {
  26. // "Run" the target, calling "toSQL" on the builder, returning
  27. // an object or array of queries to run, each of which are run on
  28. // a single connection.
  29. run: function run() {
  30. var runner = this;
  31. return _bluebird2.default.using(this.ensureConnection(), function (connection) {
  32. runner.connection = connection;
  33. runner.client.emit('start', runner.builder);
  34. runner.builder.emit('start', runner.builder);
  35. var sql = runner.builder.toSQL();
  36. if (runner.builder._debug) {
  37. helpers.debugLog(sql);
  38. }
  39. if ((0, _isArray3.default)(sql)) {
  40. return runner.queryArray(sql);
  41. }
  42. return runner.query(sql);
  43. })
  44. // If there are any "error" listeners, we fire an error event
  45. // and then re-throw the error to be eventually handled by
  46. // the promise chain. Useful if you're wrapping in a custom `Promise`.
  47. .catch(function (err) {
  48. if (runner.builder._events && runner.builder._events.error) {
  49. runner.builder.emit('error', err);
  50. }
  51. throw err;
  52. })
  53. // Fire a single "end" event on the builder when
  54. // all queries have successfully completed.
  55. .tap(function () {
  56. runner.builder.emit('end');
  57. });
  58. },
  59. // Stream the result set, by passing through to the dialect's streaming
  60. // capabilities. If the options are
  61. stream: function stream(options, handler) {
  62. // If we specify stream(handler).then(...
  63. if (arguments.length === 1) {
  64. if (typeof options === 'function') {
  65. handler = options;
  66. options = {};
  67. }
  68. }
  69. // Determines whether we emit an error or throw here.
  70. var hasHandler = typeof handler === 'function';
  71. // Lazy-load the "PassThrough" dependency.
  72. PassThrough = PassThrough || require('readable-stream').PassThrough;
  73. var runner = this;
  74. var stream = new PassThrough({ objectMode: true });
  75. var promise = _bluebird2.default.using(this.ensureConnection(), function (connection) {
  76. runner.connection = connection;
  77. var sql = runner.builder.toSQL();
  78. var err = new Error('The stream may only be used with a single query statement.');
  79. if ((0, _isArray3.default)(sql)) {
  80. if (hasHandler) throw err;
  81. stream.emit('error', err);
  82. }
  83. return runner.client.stream(runner.connection, sql, stream, options);
  84. });
  85. // If a function is passed to handle the stream, send the stream
  86. // there and return the promise, otherwise just return the stream
  87. // and the promise will take care of itsself.
  88. if (hasHandler) {
  89. handler(stream);
  90. return promise;
  91. }
  92. return stream;
  93. },
  94. // Allow you to pipe the stream to a writable stream.
  95. pipe: function pipe(writable, options) {
  96. return this.stream(options).pipe(writable);
  97. },
  98. // "Runs" a query, returning a promise. All queries specified by the builder are guaranteed
  99. // to run in sequence, and on the same connection, especially helpful when schema building
  100. // and dealing with foreign key constraints, etc.
  101. query: _bluebird2.default.method(function (obj) {
  102. var _this = this;
  103. this.builder.emit('query', (0, _assign3.default)({ __knexUid: this.connection.__knexUid }, obj));
  104. var runner = this;
  105. var queryPromise = this.client.query(this.connection, obj);
  106. if (obj.timeout) {
  107. queryPromise = queryPromise.timeout(obj.timeout);
  108. }
  109. return queryPromise.then(function (resp) {
  110. var processedResponse = _this.client.processResponse(resp, runner);
  111. _this.builder.emit('query-response', processedResponse, (0, _assign3.default)({ __knexUid: _this.connection.__knexUid }, obj), _this.builder);
  112. _this.client.emit('query-response', processedResponse, (0, _assign3.default)({ __knexUid: _this.connection.__knexUid }, obj), _this.builder);
  113. return processedResponse;
  114. }).catch(_bluebird2.default.TimeoutError, function (error) {
  115. var timeout = obj.timeout,
  116. sql = obj.sql,
  117. bindings = obj.bindings;
  118. var cancelQuery = void 0;
  119. if (obj.cancelOnTimeout) {
  120. cancelQuery = _this.client.cancelQuery(_this.connection);
  121. } else {
  122. cancelQuery = _bluebird2.default.resolve();
  123. }
  124. return cancelQuery.catch(function (cancelError) {
  125. // cancellation failed
  126. throw (0, _assign3.default)(cancelError, {
  127. message: 'After query timeout of ' + timeout + 'ms exceeded, cancelling of query failed.',
  128. sql: sql, bindings: bindings, timeout: timeout
  129. });
  130. }).then(function () {
  131. // cancellation succeeded, rethrow timeout error
  132. throw (0, _assign3.default)(error, {
  133. message: 'Defined query timeout of ' + timeout + 'ms exceeded when running query.',
  134. sql: sql, bindings: bindings, timeout: timeout
  135. });
  136. });
  137. }).catch(function (error) {
  138. _this.builder.emit('query-error', error, (0, _assign3.default)({ __knexUid: _this.connection.__knexUid }, obj));
  139. throw error;
  140. });
  141. }),
  142. // In the case of the "schema builder" we call `queryArray`, which runs each
  143. // of the queries in sequence.
  144. queryArray: function queryArray(queries) {
  145. return queries.length === 1 ? this.query(queries[0]) : _bluebird2.default.bind(this).return(queries).reduce(function (memo, query) {
  146. return this.query(query).then(function (resp) {
  147. memo.push(resp);
  148. return memo;
  149. });
  150. }, []);
  151. },
  152. // Check whether there's a transaction flag, and that it has a connection.
  153. ensureConnection: function ensureConnection() {
  154. var _this2 = this;
  155. return _bluebird2.default.try(function () {
  156. return _this2.connection || new _bluebird2.default(function (resolver, rejecter) {
  157. // need to return promise or null from handler to prevent warning from bluebird
  158. return _this2.client.acquireConnection().then(resolver).catch(_bluebird2.default.TimeoutError, function (error) {
  159. if (_this2.builder) {
  160. error.sql = _this2.builder.sql;
  161. error.bindings = _this2.builder.bindings;
  162. }
  163. throw error;
  164. }).catch(rejecter);
  165. });
  166. }).disposer(function () {
  167. // need to return promise or null from handler to prevent warning from bluebird
  168. return _this2.client.releaseConnection(_this2.connection);
  169. });
  170. }
  171. });
  172. exports.default = Runner;
  173. module.exports = exports['default'];