index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _typeof2 = require('babel-runtime/helpers/typeof');
  4. var _typeof3 = _interopRequireDefault(_typeof2);
  5. var _stringify = require('babel-runtime/core-js/json/stringify');
  6. var _stringify2 = _interopRequireDefault(_stringify);
  7. var _includes2 = require('lodash/includes');
  8. var _includes3 = _interopRequireDefault(_includes2);
  9. var _isString2 = require('lodash/isString');
  10. var _isString3 = _interopRequireDefault(_isString2);
  11. var _isArray2 = require('lodash/isArray');
  12. var _isArray3 = _interopRequireDefault(_isArray2);
  13. var _extend2 = require('lodash/extend');
  14. var _extend3 = _interopRequireDefault(_extend2);
  15. var _map2 = require('lodash/map');
  16. var _map3 = _interopRequireDefault(_map2);
  17. var _assign2 = require('lodash/assign');
  18. var _assign3 = _interopRequireDefault(_assign2);
  19. var _inherits = require('inherits');
  20. var _inherits2 = _interopRequireDefault(_inherits);
  21. var _client = require('../../client');
  22. var _client2 = _interopRequireDefault(_client);
  23. var _bluebird = require('bluebird');
  24. var _bluebird2 = _interopRequireDefault(_bluebird);
  25. var _helpers = require('../../helpers');
  26. var _compiler = require('./query/compiler');
  27. var _compiler2 = _interopRequireDefault(_compiler);
  28. var _columncompiler = require('./schema/columncompiler');
  29. var _columncompiler2 = _interopRequireDefault(_columncompiler);
  30. var _tablecompiler = require('./schema/tablecompiler');
  31. var _tablecompiler2 = _interopRequireDefault(_tablecompiler);
  32. var _compiler3 = require('./schema/compiler');
  33. var _compiler4 = _interopRequireDefault(_compiler3);
  34. var _string = require('../../query/string');
  35. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  36. function Client_PG(config) {
  37. _client2.default.apply(this, arguments);
  38. if (config.returning) {
  39. this.defaultReturning = config.returning;
  40. }
  41. if (config.searchPath) {
  42. this.searchPath = config.searchPath;
  43. }
  44. if (config.version) {
  45. this.version = config.version;
  46. }
  47. }
  48. // PostgreSQL
  49. // -------
  50. (0, _inherits2.default)(Client_PG, _client2.default);
  51. (0, _assign3.default)(Client_PG.prototype, {
  52. queryCompiler: function queryCompiler() {
  53. return new (Function.prototype.bind.apply(_compiler2.default, [null].concat([this], Array.prototype.slice.call(arguments))))();
  54. },
  55. columnCompiler: function columnCompiler() {
  56. return new (Function.prototype.bind.apply(_columncompiler2.default, [null].concat([this], Array.prototype.slice.call(arguments))))();
  57. },
  58. schemaCompiler: function schemaCompiler() {
  59. return new (Function.prototype.bind.apply(_compiler4.default, [null].concat([this], Array.prototype.slice.call(arguments))))();
  60. },
  61. tableCompiler: function tableCompiler() {
  62. return new (Function.prototype.bind.apply(_tablecompiler2.default, [null].concat([this], Array.prototype.slice.call(arguments))))();
  63. },
  64. dialect: 'postgresql',
  65. driverName: 'pg',
  66. _driver: function _driver() {
  67. return require('pg');
  68. },
  69. _escapeBinding: (0, _string.makeEscape)({
  70. escapeArray: function escapeArray(val, esc) {
  71. return esc(arrayString(val, esc));
  72. },
  73. escapeString: function escapeString(str) {
  74. var hasBackslash = false;
  75. var escaped = '\'';
  76. for (var i = 0; i < str.length; i++) {
  77. var c = str[i];
  78. if (c === '\'') {
  79. escaped += c + c;
  80. } else if (c === '\\') {
  81. escaped += c + c;
  82. hasBackslash = true;
  83. } else {
  84. escaped += c;
  85. }
  86. }
  87. escaped += '\'';
  88. if (hasBackslash === true) {
  89. escaped = 'E' + escaped;
  90. }
  91. return escaped;
  92. },
  93. escapeObject: function escapeObject(val, prepareValue, timezone) {
  94. var seen = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
  95. if (val && typeof val.toPostgres === 'function') {
  96. seen = seen || [];
  97. if (seen.indexOf(val) !== -1) {
  98. throw new Error('circular reference detected while preparing "' + val + '" for query');
  99. }
  100. seen.push(val);
  101. return prepareValue(val.toPostgres(prepareValue), seen);
  102. }
  103. return (0, _stringify2.default)(val);
  104. }
  105. }),
  106. wrapIdentifierImpl: function wrapIdentifierImpl(value) {
  107. if (value === '*') return value;
  108. var arrayAccessor = '';
  109. var arrayAccessorMatch = value.match(/(.*?)(\[[0-9]+\])/);
  110. if (arrayAccessorMatch) {
  111. value = arrayAccessorMatch[1];
  112. arrayAccessor = arrayAccessorMatch[2];
  113. }
  114. return '"' + value.replace(/"/g, '""') + '"' + arrayAccessor;
  115. },
  116. // Get a raw connection, called by the `pool` whenever a new
  117. // connection needs to be added to the pool.
  118. acquireRawConnection: function acquireRawConnection() {
  119. var client = this;
  120. return new _bluebird2.default(function (resolver, rejecter) {
  121. var connection = new client.driver.Client(client.connectionSettings);
  122. connection.connect(function (err, connection) {
  123. if (err) {
  124. return rejecter(err);
  125. }
  126. connection.on('error', function (err) {
  127. connection.__knex__disposed = err;
  128. });
  129. connection.on('end', function (err) {
  130. connection.__knex__disposed = err || 'Connection ended unexpectedly';
  131. });
  132. if (!client.version) {
  133. return client.checkVersion(connection).then(function (version) {
  134. client.version = version;
  135. resolver(connection);
  136. });
  137. }
  138. resolver(connection);
  139. });
  140. }).tap(function setSearchPath(connection) {
  141. return client.setSchemaSearchPath(connection);
  142. });
  143. },
  144. // Used to explicitly close a connection, called internally by the pool
  145. // when a connection times out or the pool is shutdown.
  146. destroyRawConnection: function destroyRawConnection(connection) {
  147. return _bluebird2.default.fromCallback(connection.end.bind(connection));
  148. },
  149. // In PostgreSQL, we need to do a version check to do some feature
  150. // checking on the database.
  151. checkVersion: function checkVersion(connection) {
  152. return new _bluebird2.default(function (resolver, rejecter) {
  153. connection.query('select version();', function (err, resp) {
  154. if (err) return rejecter(err);
  155. resolver(/^PostgreSQL (.*?)( |$)/.exec(resp.rows[0].version)[1]);
  156. });
  157. });
  158. },
  159. // Position the bindings for the query. The escape sequence for question mark
  160. // is \? (e.g. knex.raw("\\?") since javascript requires '\' to be escaped too...)
  161. positionBindings: function positionBindings(sql) {
  162. var questionCount = 0;
  163. return sql.replace(/(\\*)(\?)/g, function (match, escapes) {
  164. if (escapes.length % 2) {
  165. return '?';
  166. } else {
  167. questionCount++;
  168. return '$' + questionCount;
  169. }
  170. });
  171. },
  172. setSchemaSearchPath: function setSchemaSearchPath(connection, searchPath) {
  173. var path = searchPath || this.searchPath;
  174. if (!path) return _bluebird2.default.resolve(true);
  175. if (!(0, _isArray3.default)(path) && !(0, _isString3.default)(path)) {
  176. throw new TypeError('knex: Expected searchPath to be Array/String, got: ' + (typeof path === 'undefined' ? 'undefined' : (0, _typeof3.default)(path)));
  177. }
  178. if ((0, _isString3.default)(path)) {
  179. if ((0, _includes3.default)(path, ',')) {
  180. var parts = path.split(',');
  181. var arraySyntax = '[' + (0, _map3.default)(parts, function (searchPath) {
  182. return '\'' + searchPath + '\'';
  183. }).join(', ') + ']';
  184. (0, _helpers.warn)('Detected comma in searchPath "' + path + '".' + ('If you are trying to specify multiple schemas, use Array syntax: ' + arraySyntax));
  185. }
  186. path = [path];
  187. }
  188. path = (0, _map3.default)(path, function (schemaName) {
  189. return '"' + schemaName + '"';
  190. }).join(',');
  191. return new _bluebird2.default(function (resolver, rejecter) {
  192. connection.query('set search_path to ' + path, function (err) {
  193. if (err) return rejecter(err);
  194. resolver(true);
  195. });
  196. });
  197. },
  198. _stream: function _stream(connection, obj, stream, options) {
  199. var PGQueryStream = process.browser ? undefined : require('pg-query-stream');
  200. var sql = obj.sql;
  201. return new _bluebird2.default(function (resolver, rejecter) {
  202. var queryStream = connection.query(new PGQueryStream(sql, obj.bindings, options));
  203. queryStream.on('error', function (error) {
  204. stream.emit('error', error);
  205. });
  206. // 'error' is not propagated by .pipe, but it breaks the pipe
  207. stream.on('error', function (error) {
  208. // Ensure the queryStream is closed so the connection can be released.
  209. queryStream.close();
  210. rejecter(error);
  211. });
  212. // 'end' IS propagated by .pipe, by default
  213. stream.on('end', resolver);
  214. queryStream.pipe(stream);
  215. });
  216. },
  217. // Runs the query on the specified connection, providing the bindings
  218. // and any other necessary prep work.
  219. _query: function _query(connection, obj) {
  220. var sql = obj.sql;
  221. if (obj.options) sql = (0, _extend3.default)({ text: sql }, obj.options);
  222. return new _bluebird2.default(function (resolver, rejecter) {
  223. connection.query(sql, obj.bindings, function (err, response) {
  224. if (err) return rejecter(err);
  225. obj.response = response;
  226. resolver(obj);
  227. });
  228. });
  229. },
  230. // Ensures the response is returned in the same format as other clients.
  231. processResponse: function processResponse(obj, runner) {
  232. var resp = obj.response;
  233. if (obj.output) return obj.output.call(runner, resp);
  234. if (obj.method === 'raw') return resp;
  235. var returning = obj.returning;
  236. if (resp.command === 'SELECT') {
  237. if (obj.method === 'first') return resp.rows[0];
  238. if (obj.method === 'pluck') return (0, _map3.default)(resp.rows, obj.pluck);
  239. return resp.rows;
  240. }
  241. if (returning) {
  242. var returns = [];
  243. for (var i = 0, l = resp.rows.length; i < l; i++) {
  244. var row = resp.rows[i];
  245. if (returning === '*' || Array.isArray(returning)) {
  246. returns[i] = row;
  247. } else {
  248. returns[i] = row[returning];
  249. }
  250. }
  251. return returns;
  252. }
  253. if (resp.command === 'UPDATE' || resp.command === 'DELETE') {
  254. return resp.rowCount;
  255. }
  256. return resp;
  257. }
  258. });
  259. function arrayString(arr, esc) {
  260. var result = '{';
  261. for (var i = 0; i < arr.length; i++) {
  262. if (i > 0) result += ',';
  263. var val = arr[i];
  264. if (val === null || typeof val === 'undefined') {
  265. result += 'NULL';
  266. } else if (Array.isArray(val)) {
  267. result += arrayString(val, esc);
  268. } else if (typeof val === 'number') {
  269. result += val;
  270. } else {
  271. result += (0, _stringify2.default)(typeof val === 'string' ? val : esc(val));
  272. }
  273. }
  274. return result + '}';
  275. }
  276. exports.default = Client_PG;
  277. module.exports = exports['default'];