2013-05-02 00:21:49 -04:00
|
|
|
var Q = require('q');
|
|
|
|
var _ = require('underscore');
|
|
|
|
|
|
|
|
// Setup is called with the context of the current client.
|
|
|
|
exports.setup = function(Client, name, options) {
|
|
|
|
if (!options.connection) {
|
|
|
|
throw new Error('The database connection properties must be specified.');
|
|
|
|
}
|
|
|
|
this.name = name;
|
|
|
|
this.debug = options.debug;
|
|
|
|
this.connectionSettings = options.connection;
|
|
|
|
this.grammar = Client.grammar;
|
|
|
|
this.schemaGrammar = Client.schemaGrammar;
|
|
|
|
|
|
|
|
// Extend the genericPool with the options
|
|
|
|
// passed into the init under the "pool" option.
|
|
|
|
var instance = this;
|
2013-05-03 00:20:51 -04:00
|
|
|
this.pool = require('generic-pool').Pool(_.extend({
|
2013-05-02 00:21:49 -04:00
|
|
|
name: 'pool-' + name,
|
2013-05-03 00:20:51 -04:00
|
|
|
min: 2,
|
|
|
|
max: 10,
|
|
|
|
log: false,
|
|
|
|
idleTimeoutMillis: 30000,
|
2013-05-02 00:21:49 -04:00
|
|
|
create: function(callback) {
|
2013-05-03 00:20:51 -04:00
|
|
|
var conn = instance.getRawConnection();
|
|
|
|
conn.__cid = _.uniqueId('__cid');
|
|
|
|
callback(null, conn);
|
2013-05-02 00:21:49 -04:00
|
|
|
},
|
2013-05-03 00:20:51 -04:00
|
|
|
destroy: function(client) { client.end(); }
|
2013-05-02 00:21:49 -04:00
|
|
|
}, this.poolDefaults, options.pool));
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.protoProps = {
|
|
|
|
|
2013-05-03 18:10:22 -04:00
|
|
|
// Execute a query on the specified Builder or QueryBuilder
|
|
|
|
// interface. If a `connection` is specified, use it, otherwise
|
2013-05-03 12:51:54 -04:00
|
|
|
// acquire a connection, and then dispose of it when we're done.
|
2013-05-03 18:10:22 -04:00
|
|
|
query: function(builder) {
|
2013-05-03 23:16:15 -04:00
|
|
|
var emptyConnection = !builder._connection;
|
2013-05-03 18:10:22 -04:00
|
|
|
var debug = this.debug || builder.debug;
|
2013-05-03 23:16:15 -04:00
|
|
|
var instance = this;
|
|
|
|
return Q((builder._connection || this.getConnection()))
|
2013-05-03 12:51:54 -04:00
|
|
|
.then(function(conn) {
|
2013-05-03 18:10:22 -04:00
|
|
|
var promise;
|
|
|
|
|
|
|
|
// Prep the SQL associated with the builder.
|
|
|
|
builder.sql = builder.toSql();
|
2013-05-03 23:16:15 -04:00
|
|
|
builder.bindings = builder._cleanBindings();
|
|
|
|
builder = instance.prepData(builder);
|
2013-05-03 18:10:22 -04:00
|
|
|
|
|
|
|
// If we have a debug flag set, console.log the query.
|
|
|
|
if (debug) console.log(_.extend(builder, {__cid: conn.__cid}));
|
|
|
|
|
|
|
|
// If it's an array (in the case of schema builders), resolve with
|
|
|
|
// all of the queries, called with the same connection, otherwise
|
2013-05-03 23:16:15 -04:00
|
|
|
conn.query = _.bind(conn.query, conn);
|
2013-05-03 18:10:22 -04:00
|
|
|
if (_.isArray(builder.sql)) {
|
|
|
|
promise = Q.all(_.map(builder.sql, function(sql) {
|
2013-05-03 23:16:15 -04:00
|
|
|
return Q.nfcall(conn.query, sql, (builder.bindings || []));
|
2013-05-03 18:10:22 -04:00
|
|
|
}));
|
|
|
|
} else {
|
2013-05-03 23:16:15 -04:00
|
|
|
promise = Q.nfcall(conn.query, builder.sql, (builder.bindings || []));
|
2013-05-03 18:10:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Empty the connection after we run the query, unless one was specifically
|
|
|
|
// set (in the case of transactions, etc).
|
|
|
|
return promise.fin(function() {
|
|
|
|
if (emptyConnection) instance.pool.release(conn);
|
|
|
|
});
|
2013-05-03 12:51:54 -04:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2013-05-03 00:20:51 -04:00
|
|
|
prepData: function(data) {
|
|
|
|
return data;
|
|
|
|
},
|
|
|
|
|
|
|
|
prepResp: function(resp) {
|
|
|
|
return resp;
|
|
|
|
},
|
|
|
|
|
|
|
|
// Retrieves a connection from the connection pool,
|
|
|
|
// returning a promise.
|
|
|
|
getConnection: function() {
|
|
|
|
return Q.ninvoke(this.pool, 'acquire');
|
|
|
|
},
|
|
|
|
|
|
|
|
// Releases a connection from the connection pool,
|
|
|
|
// returning a promise.
|
|
|
|
releaseConnection: function(conn) {
|
|
|
|
return Q.ninvoke(this.pool, 'release', conn);
|
|
|
|
},
|
|
|
|
|
2013-05-02 00:21:49 -04:00
|
|
|
// Begins a transaction statement on the instance,
|
|
|
|
// resolving with the connection of the current transaction.
|
|
|
|
startTransaction: function() {
|
2013-05-03 00:20:51 -04:00
|
|
|
return this.getConnection().then(function(connection) {
|
|
|
|
return Q.ninvoke(connection, 'query', 'begin;', []).then(function() {
|
|
|
|
return connection;
|
|
|
|
});
|
2013-05-02 00:21:49 -04:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2013-05-03 00:20:51 -04:00
|
|
|
finishTransaction: function(type, trans, dfd) {
|
|
|
|
Q.ninvoke(trans.connection, 'query', type + ';', []).then(function() {
|
|
|
|
if (type === 'commit') dfd.resolve(resp);
|
|
|
|
if (type === 'rollback') dfd.reject(resp);
|
|
|
|
}).fin(function() {
|
2013-05-02 00:21:49 -04:00
|
|
|
trans.connection.end();
|
|
|
|
trans.connection = null;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-05-03 10:03:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.grammar = {
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.schemaGrammar = {
|
|
|
|
|
2013-05-03 23:16:15 -04:00
|
|
|
// Compile a create table command.
|
|
|
|
compileCreateTable: function(blueprint, command) {
|
|
|
|
var columns = this.getColumns(blueprint).join(', ');
|
|
|
|
return 'create table ' + this.wrapTable(blueprint) + ' (' + columns + ')';
|
|
|
|
},
|
|
|
|
|
2013-05-03 10:03:44 -04:00
|
|
|
// Compile a drop table command.
|
|
|
|
compileDropTable: function(blueprint, command) {
|
|
|
|
return 'drop table ' + this.wrapTable(blueprint);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Compile a drop table (if exists) command.
|
|
|
|
compileDropTableIfExists: function(blueprint, command) {
|
|
|
|
return 'drop table if exists ' + this.wrapTable(blueprint);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|