UNPKG

waterline-postgresql

Version:
265 lines (216 loc) 7.41 kB
var _ = require('lodash') var Promise = require('./promise') var helpers = require('./helpers') var Raw = require('./raw') var Runner = require('./runner') var Formatter = require('./formatter') var Transaction = require('./transaction') var QueryBuilder = require('./query/builder') var QueryCompiler = require('./query/compiler') var SchemaBuilder = require('./schema/builder') var SchemaCompiler = require('./schema/compiler') var TableBuilder = require('./schema/tablebuilder') var TableCompiler = require('./schema/tablecompiler') var ColumnBuilder = require('./schema/columnbuilder') var ColumnCompiler = require('./schema/columncompiler') var Pool2 = require('pool2') var inherits = require('inherits') var EventEmitter = require('events').EventEmitter var SqlString = require('./query/string') var assign = require('lodash/object/assign') var uniqueId = require('lodash/utility/uniqueId') var cloneDeep = require('lodash/lang/cloneDeep') var debug = require('debug')('knex:client') var debugQuery = require('debug')('knex:query') // The base client provides the general structure // for a dialect specific client object. function Client(config = {}) { this.config = config this.connectionSettings = cloneDeep(config.connection || {}) if (this.driverName && config.connection) { this.initializeDriver() if (!config.pool || (config.pool && config.pool.max !== 0)) { this.initializePool(config) } } this.valueForUndefined = this.raw('DEFAULT'); if (config.useNullAsDefault) { this.valueForUndefined = null } } inherits(Client, EventEmitter) assign(Client.prototype, { Formatter: Formatter, formatter: function() { return new this.Formatter(this) }, QueryBuilder: QueryBuilder, queryBuilder: function() { return new this.QueryBuilder(this) }, QueryCompiler: QueryCompiler, queryCompiler: function(builder) { return new this.QueryCompiler(this, builder) }, SchemaBuilder: SchemaBuilder, schemaBuilder: function() { return new this.SchemaBuilder(this) }, SchemaCompiler: SchemaCompiler, schemaCompiler: function(builder) { return new this.SchemaCompiler(this, builder) }, TableBuilder: TableBuilder, tableBuilder: function(type, tableName, fn) { return new this.TableBuilder(this, type, tableName, fn) }, TableCompiler: TableCompiler, tableCompiler: function(tableBuilder) { return new this.TableCompiler(this, tableBuilder) }, ColumnBuilder: ColumnBuilder, columnBuilder: function(tableBuilder, type, args) { return new this.ColumnBuilder(this, tableBuilder, type, args) }, ColumnCompiler: ColumnCompiler, columnCompiler: function(tableBuilder, columnBuilder) { return new this.ColumnCompiler(this, tableBuilder, columnBuilder) }, Runner: Runner, runner: function(connection) { return new this.Runner(this, connection) }, SqlString: SqlString, Transaction: Transaction, transaction: function(container, config, outerTx) { return new this.Transaction(this, container, config, outerTx) }, Raw: Raw, raw: function() { var raw = new this.Raw(this) return raw.set.apply(raw, arguments) }, query: function(connection, obj) { if (typeof obj === 'string') obj = {sql: obj} this.emit('query', assign({__knexUid: connection.__knexUid}, obj)) debugQuery(obj.sql) return this._query.call(this, connection, obj).catch((err) => { err.message = SqlString.format(obj.sql, obj.bindings) + ' - ' + err.message this.emit('query-error', err, obj) throw err }) }, stream: function(connection, obj, stream, options) { if (typeof obj === 'string') obj = {sql: obj} this.emit('query', assign({__knexUid: connection.__knexUid}, obj)) debugQuery(obj.sql) return this._stream.call(this, connection, obj, stream, options) }, prepBindings: function(bindings) { return _.map(bindings, function(binding) { return binding === undefined ? this.valueForUndefined : binding }, this); }, wrapIdentifier: function(value) { return (value !== '*' ? '"' + value.replace(/"/g, '""') + '"' : '*') }, initializeDriver: function() { try { this.driver = this._driver() } catch (e) { helpers.exit('Knex: run\n$ npm install ' + this.driverName + ' --save' + '\n' + e.stack) } }, Pool: Pool2, initializePool: function(config) { if (this.pool) this.destroy() this.pool = new this.Pool(assign(this.poolDefaults(config.pool || {}), config.pool)) this.pool.on('error', function(err) { helpers.error('Pool2 - ' + err) }) this.pool.on('warn', function(msg) { helpers.warn('Pool2 - ' + msg) }) }, poolDefaults: function(poolConfig) { var dispose, client = this if (poolConfig.destroy) { helpers.deprecate('config.pool.destroy', 'config.pool.dispose') dispose = poolConfig.destroy } return { min: 2, max: 10, acquire: function(callback) { client.acquireRawConnection() .tap(function(connection) { connection.__knexUid = uniqueId('__knexUid') if (poolConfig.afterCreate) { return Promise.promisify(poolConfig.afterCreate)(connection) } }) .nodeify(callback) }, dispose: function(connection, callback) { if (poolConfig.beforeDestroy) { poolConfig.beforeDestroy(connection, function() { if (connection !== undefined) { client.destroyRawConnection(connection, callback) } }) } else if (connection !== void 0) { client.destroyRawConnection(connection, callback) } } } }, // Acquire a connection from the pool. acquireConnection: function() { var client = this return new Promise(function(resolver, rejecter) { if (!client.pool) { return rejecter(new Error('There is no pool defined on the current client')) } client.pool.acquire(function(err, connection) { if (err) return rejecter(err) debug('acquiring connection from pool: %s', connection.__knexUid) resolver(connection) }) }) }, // Releases a connection back to the connection pool, // returning a promise resolved when the connection is released. releaseConnection: function(connection) { var pool = this.pool return new Promise(function(resolver) { debug('releasing connection to pool: %s', connection.__knexUid) pool.release(connection) resolver() }) }, // Destroy the current connection pool for the client. destroy: function(callback) { var client = this var promise = new Promise(function(resolver) { if (!client.pool) return resolver() client.pool.end(function() { client.pool = undefined resolver() }) }) // Allow either a callback or promise interface for destruction. if (typeof callback === 'function') { promise.nodeify(callback) } else { return promise } }, // Return the database being used by this client. database: function() { return this.connectionSettings.database }, toString: function() { return '[object KnexClient]' } }) module.exports = Client