Skip to content

Commit 3eef52d

Browse files
committed
Merge tag 'v6.1.6' into cdb-6.1
Bump version
2 parents 3c81aea + b0a2fe4 commit 3eef52d

File tree

11 files changed

+170
-85
lines changed

11 files changed

+170
-85
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ var config = {
7272

7373

7474
//this initializes a connection pool
75-
//it will keep idle connections open for a 30 seconds
75+
//it will keep idle connections open for 30 seconds
7676
//and set a limit of maximum 10 idle clients
7777
var pool = new pg.Pool(config);
7878

@@ -83,8 +83,8 @@ pool.connect(function(err, client, done) {
8383
return console.error('error fetching client from pool', err);
8484
}
8585
client.query('SELECT $1::int AS number', ['1'], function(err, result) {
86-
//call `done()` to release the client back to the pool
87-
done();
86+
//call `done(err)` to release the client back to the pool (or destroy it if there is an error)
87+
done(err);
8888

8989
if(err) {
9090
return console.error('error running query', err);

lib/client.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Client.prototype.connect = function(callback) {
173173
self.readyForQuery = true;
174174
self._pulseQueryQueue();
175175
if(activeQuery) {
176-
activeQuery.handleReadyForQuery();
176+
activeQuery.handleReadyForQuery(con);
177177
}
178178
});
179179

@@ -186,6 +186,7 @@ Client.prototype.connect = function(callback) {
186186
if(!callback) {
187187
return self.emit('error', error);
188188
}
189+
con.end(); // make sure ECONNRESET errors don't cause error events
189190
callback(error);
190191
callback = null;
191192
});

lib/connection.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ var defaults = require('./defaults');
1515
var Writer = require('buffer-writer');
1616
var Reader = require('packet-reader');
1717

18+
var indexOf =
19+
'indexOf' in Buffer.prototype ?
20+
function indexOf(buffer, value, start) {
21+
return buffer.indexOf(value, start);
22+
} :
23+
function indexOf(buffer, value, start) {
24+
for (var i = start, len = buffer.length; i < len; i++) {
25+
if (buffer[i] === value) {
26+
return i;
27+
}
28+
}
29+
30+
return -1;
31+
};
32+
1833
var TEXT_MODE = 0;
1934
var BINARY_MODE = 1;
2035
var Connection = function(config) {
@@ -653,8 +668,9 @@ Connection.prototype.readBytes = function(buffer, length) {
653668

654669
Connection.prototype.parseCString = function(buffer) {
655670
var start = this.offset;
656-
while(buffer[this.offset++] !== 0) { }
657-
return buffer.toString(this.encoding, start, this.offset - 1);
671+
var end = indexOf(buffer, 0, start);
672+
this.offset = end + 1;
673+
return buffer.toString(this.encoding, start, end);
658674
};
659675
//end parsing methods
660676
module.exports = Connection;

lib/query.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,19 @@ Query.prototype.handleRowDescription = function(msg) {
8080
};
8181

8282
Query.prototype.handleDataRow = function(msg) {
83-
var row = this._result.parseRow(msg.fields);
83+
var row;
84+
85+
if (this._canceledDueToError) {
86+
return;
87+
}
88+
89+
try {
90+
row = this._result.parseRow(msg.fields);
91+
} catch (err) {
92+
this._canceledDueToError = err;
93+
return;
94+
}
95+
8496
this.emit('row', row, this._result);
8597
if (this._accumulateRows) {
8698
this._result.addRow(row);
@@ -104,9 +116,9 @@ Query.prototype.handleEmptyQuery = function(con) {
104116
}
105117
};
106118

107-
Query.prototype.handleReadyForQuery = function() {
119+
Query.prototype.handleReadyForQuery = function(con) {
108120
if(this._canceledDueToError) {
109-
return this.handleError(this._canceledDueToError);
121+
return this.handleError(this._canceledDueToError, con);
110122
}
111123
if(this.callback) {
112124
this.callback(null, this._result);

lib/result.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
var types = require('pg-types');
10+
var escape = require('js-string-escape');
1011

1112
//result object returned from query
1213
//in the 'end' event and also
@@ -75,13 +76,13 @@ Result.prototype.addRow = function(row) {
7576

7677
var inlineParser = function(fieldName, i) {
7778
return "\nthis['" +
78-
//fields containing single quotes will break
79-
//the evaluated javascript unless they are escaped
80-
//see https://github.com/brianc/node-postgres/issues/507
81-
//Addendum: However, we need to make sure to replace all
82-
//occurences of apostrophes, not just the first one.
83-
//See https://github.com/brianc/node-postgres/issues/934
84-
fieldName.replace(/'/g, "\\'") +
79+
// fields containing single quotes will break
80+
// the evaluated javascript unless they are escaped
81+
// see https://github.com/brianc/node-postgres/issues/507
82+
// Addendum: However, we need to make sure to replace all
83+
// occurences of apostrophes, not just the first one.
84+
// See https://github.com/brianc/node-postgres/issues/934
85+
escape(fieldName) +
8586
"'] = " +
8687
"rowData[" + i + "] == null ? null : parsers[" + i + "](rowData[" + i + "]);";
8788
};

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg",
3-
"version": "6.1.2",
3+
"version": "6.1.6",
44
"description": "PostgreSQL client - pure javascript & libpq with the same API",
55
"keywords": [
66
"postgres",
@@ -19,6 +19,7 @@
1919
"main": "./lib",
2020
"dependencies": {
2121
"buffer-writer": "1.0.1",
22+
"js-string-escape": "1.0.1",
2223
"packet-reader": "0.2.0",
2324
"pg-connection-string": "0.1.3",
2425
"pg-pool": "1.*",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
var pg = require('./test-helper').pg
2+
3+
var sql = 'SELECT 1 AS "\\\'/*", 2 AS "\\\'*/\n + process.exit(-1)] = null;\n//"'
4+
5+
var client = new pg.Client()
6+
client.connect()
7+
client.query(sql, function (err, res) {
8+
if (err) throw err
9+
client.end()
10+
})

test/integration/client/heroku-pgpass-tests.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

test/integration/client/heroku-ssl-tests.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

test/integration/client/heroku.pgpass

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
var helper = require(__dirname + "/test-helper");
2+
var types = require('pg-types')
3+
4+
test('handles throws in type parsers', function() {
5+
var typeParserError = new Error('TEST: Throw in type parsers');
6+
7+
types.setTypeParser('special oid that will throw', function () {
8+
throw typeParserError;
9+
});
10+
11+
test('emits error', function() {
12+
var handled;
13+
var client = helper.client();
14+
var con = client.connection;
15+
var query = client.query('whatever');
16+
17+
handled = con.emit('readyForQuery');
18+
assert.ok(handled, "should have handled ready for query");
19+
20+
con.emit('rowDescription',{
21+
fields: [{
22+
name: 'boom',
23+
dataTypeID: 'special oid that will throw'
24+
}]
25+
});
26+
assert.ok(handled, "should have handled row description");
27+
28+
assert.emits(query, 'error', function(err) {
29+
assert.equal(err, typeParserError);
30+
});
31+
32+
handled = con.emit('dataRow', { fields: ["hi"] });
33+
assert.ok(handled, "should have handled first data row message");
34+
35+
handled = con.emit('commandComplete', { text: 'INSERT 31 1' });
36+
assert.ok(handled, "should have handled command complete");
37+
38+
handled = con.emit('readyForQuery');
39+
assert.ok(handled, "should have handled ready for query");
40+
});
41+
42+
test('calls callback with error', function() {
43+
var handled;
44+
45+
var callbackCalled = 0;
46+
47+
var client = helper.client();
48+
var con = client.connection;
49+
var query = client.query('whatever', assert.calls(function (err) {
50+
callbackCalled += 1;
51+
52+
assert.equal(callbackCalled, 1);
53+
assert.equal(err, typeParserError);
54+
}));
55+
56+
handled = con.emit('readyForQuery');
57+
assert.ok(handled, "should have handled ready for query");
58+
59+
handled = con.emit('rowDescription',{
60+
fields: [{
61+
name: 'boom',
62+
dataTypeID: 'special oid that will throw'
63+
}]
64+
});
65+
assert.ok(handled, "should have handled row description");
66+
67+
handled = con.emit('dataRow', { fields: ["hi"] });
68+
assert.ok(handled, "should have handled first data row message");
69+
70+
handled = con.emit('dataRow', { fields: ["hi"] });
71+
assert.ok(handled, "should have handled second data row message");
72+
73+
con.emit('commandComplete', { text: 'INSERT 31 1' });
74+
assert.ok(handled, "should have handled command complete");
75+
76+
handled = con.emit('readyForQuery');
77+
assert.ok(handled, "should have handled ready for query");
78+
});
79+
80+
test('rejects promise with error', function() {
81+
var handled;
82+
var client = helper.client();
83+
var con = client.connection;
84+
var query = client.query('whatever');
85+
var queryPromise = query.promise();
86+
87+
handled = con.emit('readyForQuery');
88+
assert.ok(handled, "should have handled ready for query");
89+
90+
handled = con.emit('rowDescription',{
91+
fields: [{
92+
name: 'boom',
93+
dataTypeID: 'special oid that will throw'
94+
}]
95+
});
96+
assert.ok(handled, "should have handled row description");
97+
98+
handled = con.emit('dataRow', { fields: ["hi"] });
99+
assert.ok(handled, "should have handled first data row message");
100+
101+
handled = con.emit('commandComplete', { text: 'INSERT 31 1' });
102+
assert.ok(handled, "should have handled command complete");
103+
104+
handled = con.emit('readyForQuery');
105+
assert.ok(handled, "should have handled ready for query");
106+
107+
queryPromise.catch(assert.calls(function (err) {
108+
assert.equal(err, typeParserError);
109+
}));
110+
});
111+
112+
});

0 commit comments

Comments
 (0)