Make moar tests pass
This commit is contained in:
parent
667c528ea6
commit
d2bb532d73
@ -176,13 +176,13 @@ Client.prototype.connect = function(callback) {
|
||||
con.once('end', function() {
|
||||
if ( callback ) {
|
||||
// haven't received a connection message yet !
|
||||
var err = new Error('Connection was ended during query');
|
||||
var err = new Error('Connection terminated');
|
||||
callback(err);
|
||||
callback = null;
|
||||
return;
|
||||
}
|
||||
if(self.activeQuery) {
|
||||
var disconnectError = new Error('Connection was ended during query');
|
||||
var disconnectError = new Error('Connection terminated');
|
||||
self.activeQuery.handleError(disconnectError, con);
|
||||
self.activeQuery = null;
|
||||
}
|
||||
|
@ -7,21 +7,21 @@ var NativeQuery = require('./query');
|
||||
|
||||
var Client = module.exports = function(config) {
|
||||
EventEmitter.call(this);
|
||||
if(typeof config === 'string') {
|
||||
this.connectionString = config;
|
||||
}
|
||||
this.native = new Native();
|
||||
this._queryQueue = [];
|
||||
this._connected = false;
|
||||
|
||||
//keep these on the object for legacy reasons
|
||||
//for the time being. TODO: deprecate all this jazz
|
||||
var cp = new ConnectionParameters(config);
|
||||
var cp = this.connectionParameters = new ConnectionParameters(config);
|
||||
this.user = cp.user;
|
||||
this.password = cp.password;
|
||||
this.database = cp.database;
|
||||
this.host = cp.host;
|
||||
this.port = cp.port;
|
||||
|
||||
//a hash to hold named queries
|
||||
this.namedQueries = {};
|
||||
};
|
||||
|
||||
util.inherits(Client, EventEmitter);
|
||||
@ -33,20 +33,41 @@ util.inherits(Client, EventEmitter);
|
||||
//the client will emit an error event.
|
||||
Client.prototype.connect = function(cb) {
|
||||
var self = this;
|
||||
this.native.connect(this.connectionString, function(err) {
|
||||
//error handling
|
||||
if(err) {
|
||||
if(cb) return cb(err);
|
||||
return self.emit('error', err);
|
||||
}
|
||||
|
||||
//set internal states to connected
|
||||
self._connected = true;
|
||||
self.emit('connect');
|
||||
self._pulseQueryQueue(true);
|
||||
var onError = function(err) {
|
||||
if(cb) return cb(err);
|
||||
return self.emit('error', err);
|
||||
};
|
||||
|
||||
//possibly call the optional callback
|
||||
if(cb) cb();
|
||||
this.connectionParameters.getLibpqConnectionString(function(err, conString) {
|
||||
if(err) return onError(err);
|
||||
self.native.connect(conString, function(err) {
|
||||
if(err) return onError(err);
|
||||
|
||||
//set internal states to connected
|
||||
self._connected = true;
|
||||
self.emit('connect');
|
||||
self._pulseQueryQueue(true);
|
||||
|
||||
//handle connection errors from the native layer
|
||||
self.native.on('error', function(err) {
|
||||
//error will be handled by active query
|
||||
if(self._activeQuery && self._activeQuery.state != 'end') {
|
||||
return;
|
||||
}
|
||||
self.emit('error', err);
|
||||
});
|
||||
|
||||
self.native.on('notification', function(msg) {
|
||||
self.emit('notification', {
|
||||
channel: msg.relname,
|
||||
payload: msg.extra
|
||||
});
|
||||
});
|
||||
|
||||
//possibly call the optional callback
|
||||
if(cb) cb();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -86,19 +107,27 @@ Client.prototype.query = function(config, values, callback) {
|
||||
Client.prototype.end = function(cb) {
|
||||
var self = this;
|
||||
this.native.end(function() {
|
||||
//send an error to the active query
|
||||
if(self._hasActiveQuery()) {
|
||||
var msg = 'Connection terminated';
|
||||
self._queryQueue.length = 0;
|
||||
self._activeQuery.handleError(new Error(msg));
|
||||
}
|
||||
self.emit('end');
|
||||
if(cb) cb();
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype._hasActiveQuery = function() {
|
||||
return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end';
|
||||
};
|
||||
|
||||
Client.prototype._pulseQueryQueue = function(initialConnection) {
|
||||
if(!this._connected) {
|
||||
return;
|
||||
}
|
||||
if(this._activeQuery) {
|
||||
if(this._activeQuery.state != 'error' && this._activeQuery.state != 'end') {
|
||||
return;
|
||||
}
|
||||
if(this._hasActiveQuery()) {
|
||||
return;
|
||||
}
|
||||
var query = this._queryQueue.shift();
|
||||
if(!query) {
|
||||
@ -108,7 +137,7 @@ Client.prototype._pulseQueryQueue = function(initialConnection) {
|
||||
return;
|
||||
}
|
||||
this._activeQuery = query;
|
||||
query.submit();
|
||||
query.submit(this);
|
||||
var self = this;
|
||||
query.once('_done', function() {
|
||||
self._pulseQueryQueue();
|
||||
|
@ -55,7 +55,24 @@ NativeResult.prototype.addCommandComplete = function(pq) {
|
||||
}
|
||||
};
|
||||
|
||||
NativeQuery.prototype.submit = function() {
|
||||
NativeQuery.prototype.handleError = function(err) {
|
||||
var self = this;
|
||||
//copy pq error fields into the error object
|
||||
var fields = self.native.pq.resultErrorFields();
|
||||
if(fields) {
|
||||
for(var key in fields) {
|
||||
err[key] = fields[key];
|
||||
}
|
||||
}
|
||||
if(self.callback) {
|
||||
self.callback(err);
|
||||
} else {
|
||||
self.emit('error', err);
|
||||
}
|
||||
self.state = 'error';
|
||||
}
|
||||
|
||||
NativeQuery.prototype.submit = function(client) {
|
||||
this.state = 'running';
|
||||
var self = this;
|
||||
|
||||
@ -66,9 +83,7 @@ NativeQuery.prototype.submit = function() {
|
||||
|
||||
//handle possible query error
|
||||
if(err) {
|
||||
self.state = 'error';
|
||||
if(self.callback) return self.callback(err);
|
||||
return self.emit('error', err);
|
||||
return self.handleError(err);
|
||||
}
|
||||
|
||||
var result = new NativeResult();
|
||||
@ -91,7 +106,27 @@ NativeQuery.prototype.submit = function() {
|
||||
}
|
||||
}
|
||||
|
||||
if(this.values) {
|
||||
if(process.domain) {
|
||||
after = process.domain.bind(after);
|
||||
}
|
||||
|
||||
//named query
|
||||
if(this.name) {
|
||||
var values = (this.values||[]).map(utils.prepareValue);
|
||||
|
||||
//check if the client has already executed this named query
|
||||
//if so...just execute it again - skip the planning phase
|
||||
if(client.namedQueries[this.name]) {
|
||||
return this.native.execute(this.name, values, after);
|
||||
}
|
||||
//plan the named query the first time, then execute it
|
||||
return this.native.prepare(this.name, this.text, values.length, function(err) {
|
||||
if(err) return self.handleError(err);
|
||||
client.namedQueries[self.name] = true;
|
||||
return self.native.execute(self.name, values, after);
|
||||
})
|
||||
}
|
||||
else if(this.values) {
|
||||
var values = this.values.map(utils.prepareValue);
|
||||
this.native.query(this.text, values, after);
|
||||
} else {
|
||||
|
@ -23,7 +23,7 @@
|
||||
"nan": "~1.3.0",
|
||||
"packet-reader": "0.2.0",
|
||||
"pg-connection-string": "0.1.1",
|
||||
"pg-native": "0.5.0",
|
||||
"pg-native": "0.5.2",
|
||||
"pg-types": "1.4.0",
|
||||
"pgpass": "0.0.3"
|
||||
},
|
||||
|
@ -1,11 +1,11 @@
|
||||
return console.log('error-handling-tests.js: GET TO PASS');
|
||||
var helper = require(__dirname + '/test-helper');
|
||||
var util = require('util');
|
||||
|
||||
var createErorrClient = function() {
|
||||
var client = helper.client();
|
||||
client.on('error', function(err) {
|
||||
assert.ok(false, "client should not throw query error: " + util.inspect(err));
|
||||
client.once('error', function(err) {
|
||||
//console.log('error', util.inspect(err));
|
||||
assert.fail('Client shoud not throw error during query execution');
|
||||
});
|
||||
client.on('drain', client.end.bind(client));
|
||||
return client;
|
||||
@ -19,11 +19,8 @@ test('error handling', function(){
|
||||
var query = client.query("select omfg from yodas_dsflsd where pixistix = 'zoiks!!!'");
|
||||
|
||||
assert.emits(query, 'error', function(error) {
|
||||
test('error is a psql error', function() {
|
||||
assert.equal(error.severity, "ERROR");
|
||||
});
|
||||
assert.equal(error.severity, "ERROR");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('within a prepared statement', function() {
|
||||
@ -109,7 +106,7 @@ test('non-error calls supplied callback', function() {
|
||||
});
|
||||
|
||||
client.connect(assert.calls(function(err) {
|
||||
assert.isNull(err);
|
||||
assert.ifError(err);
|
||||
client.end();
|
||||
}))
|
||||
});
|
||||
@ -124,9 +121,11 @@ test('when connecting to invalid host', function() {
|
||||
password: '1234',
|
||||
host: 'asldkfjasdf!!#1308140.com'
|
||||
});
|
||||
|
||||
var delay = 5000;
|
||||
var tid = setTimeout(function() {
|
||||
assert(false, "When connecting to an invalid host the error event should be emitted but it has been " + delay + " and still no error event.");
|
||||
var msg = "When connecting to an invalid host the error event should be emitted but it has been " + delay + " and still no error event."
|
||||
assert(false, msg);
|
||||
}, delay);
|
||||
client.on('error', function() {
|
||||
clearTimeout(tid);
|
||||
@ -141,7 +140,7 @@ test('when connecting to invalid host with callback', function() {
|
||||
host: 'asldkfjasdf!!#1308140.com'
|
||||
});
|
||||
client.connect(function(error, client) {
|
||||
assert.ok(error);
|
||||
assert(error);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
return console.log('notice-tests.js - GET TO PASS')
|
||||
var helper = require(__dirname + '/test-helper');
|
||||
|
||||
test('emits notice message', function() {
|
||||
//TODO this doesn't work on all versions of postgres
|
||||
return false;
|
||||
|
@ -1,4 +1,3 @@
|
||||
return console.log('prepared-statement-tests: GET TO PASS');
|
||||
var helper = require(__dirname +'/test-helper');
|
||||
|
||||
test("simple, unnamed prepared statement", function(){
|
||||
|
@ -1,4 +1,4 @@
|
||||
return console.log('query-callback-error-tests: GET TO PASS');
|
||||
return console.log('query-callback-error-tests: DEPRECATED - if you want saftey in your callback, you can try/catch your own functions');
|
||||
var helper = require(__dirname + '/test-helper');
|
||||
var util = require('util');
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
return console.log('query-error-handling-prepared-statement-tests: GET TO PASS');
|
||||
var helper = require(__dirname + '/test-helper');
|
||||
var util = require('util');
|
||||
|
||||
@ -64,7 +63,7 @@ test('client end during query execution of prepared statement', function() {
|
||||
text: sleepQuery,
|
||||
values: [5] },
|
||||
assert.calls(function(err, result) {
|
||||
assert.equal(err.message, 'Connection was ended during query');
|
||||
assert.equal(err.message, 'Connection terminated');
|
||||
}));
|
||||
|
||||
query1.on('error', function(err) {
|
||||
@ -82,3 +81,4 @@ test('client end during query execution of prepared statement', function() {
|
||||
client.end();
|
||||
}));
|
||||
});
|
||||
return console.log('query-error-handling-prepared-statement-tests: GET TO PASS');
|
||||
|
@ -37,7 +37,6 @@ test("simple query interface", function() {
|
||||
});
|
||||
|
||||
test("multiple simple queries", function() {
|
||||
return console.log('MUST SUPPORT MULTIPLE SIMPLE QURIES')
|
||||
var client = helper.client();
|
||||
client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"})
|
||||
client.query("insert into bang(name) VALUES ('yes');");
|
||||
|
@ -158,11 +158,11 @@ if(!helper.config.binary) {
|
||||
client.end();
|
||||
});
|
||||
|
||||
// Set teh server timeszone to the same as used for the test,
|
||||
// Set the server timeszone to the same as used for the test,
|
||||
// otherwise (if server's timezone is ahead of GMT) in
|
||||
// textParsers.js::parseDate() the timezone offest is added to the date;
|
||||
// in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows.
|
||||
client.query('SET TIMEZONE TO GMT', [], assert.success(function(res){
|
||||
client.query('SET TIMEZONE TO GMT', assert.success(function(res){
|
||||
|
||||
// PostgreSQL supports date range of 4713 BCE to 294276 CE
|
||||
// http://www.postgresql.org/docs/9.2/static/datatype-datetime.html
|
||||
@ -186,7 +186,7 @@ if(!helper.config.binary) {
|
||||
}
|
||||
|
||||
helper.pg.connect(helper.config, assert.calls(function(err, client, done) {
|
||||
assert.isNull(err);
|
||||
assert.ifError(err);
|
||||
client.query('select null as res;', assert.calls(function(err, res) {
|
||||
assert.isNull(err);
|
||||
assert.strictEqual(res.rows[0].res, null)
|
||||
|
@ -5,36 +5,37 @@ pg = pg;
|
||||
//first make pool hold 2 clients
|
||||
pg.defaults.poolSize = 2;
|
||||
|
||||
|
||||
//get first client
|
||||
pg.connect(helper.config, assert.success(function(client, done) {
|
||||
client.id = 1;
|
||||
pg.connect(helper.config, assert.success(function(client2, done2) {
|
||||
client2.id = 2;
|
||||
var pidColName = 'procpid';
|
||||
helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) {
|
||||
console.log(isGreater)
|
||||
var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1';
|
||||
var params = ['idle'];
|
||||
if(!isGreater) {
|
||||
killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1';
|
||||
params = ['%IDLE%']
|
||||
}
|
||||
client.query('SELECT NOW()', function() {
|
||||
pg.connect(helper.config, assert.success(function(client2, done2) {
|
||||
client2.id = 2;
|
||||
var pidColName = 'procpid';
|
||||
helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) {
|
||||
var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1';
|
||||
var params = ['idle'];
|
||||
if(!isGreater) {
|
||||
killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1';
|
||||
params = ['%IDLE%']
|
||||
}
|
||||
|
||||
//subscribe to the pg error event
|
||||
assert.emits(pg, 'error', function(error, brokenClient) {
|
||||
assert.ok(error);
|
||||
assert.ok(brokenClient);
|
||||
assert.equal(client.id, brokenClient.id);
|
||||
});
|
||||
//subscribe to the pg error event
|
||||
assert.emits(pg, 'error', function(error, brokenClient) {
|
||||
assert.ok(error);
|
||||
assert.ok(brokenClient);
|
||||
assert.equal(client.id, brokenClient.id);
|
||||
});
|
||||
|
||||
//kill the connection from client
|
||||
client2.query(killIdleQuery, params, assert.success(function(res) {
|
||||
//check to make sure client connection actually was killed
|
||||
//return client2 to the pool
|
||||
done2();
|
||||
pg.end();
|
||||
//kill the connection from client
|
||||
client2.query(killIdleQuery, params, assert.success(function(res) {
|
||||
//check to make sure client connection actually was killed
|
||||
//return client2 to the pool
|
||||
done2();
|
||||
pg.end();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
|
||||
})
|
||||
}));
|
||||
|
@ -1,2 +1,3 @@
|
||||
var helper = require(__dirname + "/test-helper")
|
||||
return console.log("WAITING OF POOL SIZE 200 DOES NOT WORK")
|
||||
helper.testPoolSize(200);
|
||||
|
Loading…
Reference in New Issue
Block a user