Skip to content

Commit d5dc421

Browse files
committed
Merge origin/master
2 parents 5341a2a + 1c8b6b9 commit d5dc421

24 files changed

+270
-28
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ package-lock.json
88
dist
99
.DS_Store
1010
.vscode/
11+
manually-test-on-heroku.js

.travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ env:
1010
node_js:
1111
- lts/dubnium
1212
- lts/erbium
13+
# node 13.7 seems to have changed behavior of async iterators exiting early on streams
14+
# if 13.8 still has this problem when it comes down I'll talk to the node team about the change
15+
# in the mean time...peg to 13.6
1316
- 13.6
1417

1518
addons:

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ For richer information consult the commit log on github with referenced pull req
44

55
We do not include break-fix version release in this file.
66

7+
### pg@7.18.0
8+
9+
- This will likely be the last minor release before pg@8.0.
10+
- This version contains a few bug fixes and adds a deprecation warning for [a pending change in 8.0](https://github.com/brianc/node-postgres/issues/2009#issuecomment-579371651) which will flip the default behavior over SSL from `rejectUnauthorized` from `false` to `true` making things more secure in the general use case.
11+
712
### pg-query-stream@3.0.0
813

914
- [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API....

README.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,21 @@ When you open an issue please provide:
5050

5151
You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter.
5252

53-
### Sponsorship :star:
53+
## Sponsorship :two_hearts:
5454

55-
[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development.
55+
node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors:
5656

57-
Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md).
57+
<div align="center">
58+
<a href="https://www.timescale.com" target="_blank">
59+
<img height="80" src="https://node-postgres.com/timescale.svg" />
60+
</a>
61+
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAQAAAB0m0auAAAADElEQVR42mNkIBIAAABSAAI2VLqiAAAAAElFTkSuQmCC" />
62+
<a href="https://crate.io" target="_blank">
63+
<img height="80" src="https://node-postgres.com/crate-io.png" />
64+
</a>
65+
</div>
66+
67+
If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development.
5868

5969
## Contributing
6070

SPONSORS.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres).
1+
node-postgres is made possible by the helpful contributors from the community as well as the following generous supporters on [GitHub Sponsors](https://github.com/sponsors/brianc) and [Patreon](https://www.patreon.com/node_postgres).
22

33
# Leaders
44

55
- [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu)
66
- [Third Iron](https://thirdiron.com/)
77
- [Timescale](https://timescale.com)
88
- [Nafundi](https://nafundi.com)
9+
- [CrateDB](https://crate.io/)
910

1011
# Supporters
1112

lerna.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"useWorkspaces": true,
77
"version": "independent",
88
"ignoreChanges": [
9-
"**/*.md"
9+
"**/*.md",
10+
"**/test/**"
1011
]
1112
}

packages/pg-cursor/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-cursor",
3-
"version": "2.1.3",
3+
"version": "2.1.6",
44
"description": "Query cursor extension for node-postgres",
55
"main": "index.js",
66
"directories": {
@@ -21,7 +21,7 @@
2121
"eslint-config-prettier": "^6.4.0",
2222
"eslint-plugin-prettier": "^3.1.1",
2323
"mocha": "^6.2.2",
24-
"pg": "^7.17.1",
24+
"pg": "^7.18.2",
2525
"prettier": "^1.18.2"
2626
},
2727
"prettier": {

packages/pg-pool/index.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class PendingItem {
2525
}
2626
}
2727

28+
function throwOnDoubleRelease () {
29+
throw new Error('Release called on client which has already been released to the pool.')
30+
}
31+
2832
function promisify (Promise, callback) {
2933
if (callback) {
3034
return { callback: callback, result: undefined }
@@ -256,7 +260,7 @@ class Pool extends EventEmitter {
256260

257261
client.release = (err) => {
258262
if (released) {
259-
throw new Error('Release called on client which has already been released to the pool.')
263+
throwOnDoubleRelease()
260264
}
261265

262266
released = true
@@ -292,7 +296,8 @@ class Pool extends EventEmitter {
292296
_release (client, idleListener, err) {
293297
client.on('error', idleListener)
294298

295-
if (err || this.ending) {
299+
// TODO(bmc): expose a proper, public interface _queryable and _ending
300+
if (err || this.ending || !client._queryable || client._ending) {
296301
this._remove(client)
297302
this._pulseQueue()
298303
return

packages/pg-pool/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-pool",
3-
"version": "2.0.9",
3+
"version": "2.0.10",
44
"description": "Connection pool for node-postgres",
55
"main": "index.js",
66
"directories": {

packages/pg-pool/test/error-handling.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,14 @@ describe('pool error handling', function () {
211211
const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' })
212212
pool.connect((err) => {
213213
expect(err).to.be.an(Error)
214-
if (err.errno) {
215-
expect(err.errno).to.be('ECONNRESET')
214+
if (err.code) {
215+
expect(err.code).to.be('ECONNRESET')
216216
}
217217
})
218218
pool.connect((err) => {
219219
expect(err).to.be.an(Error)
220-
if (err.errno) {
221-
expect(err.errno).to.be('ECONNRESET')
220+
if (err.code) {
221+
expect(err.code).to.be('ECONNRESET')
222222
}
223223
closeServer.close(() => {
224224
pool.end(done)
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const Pool = require('../')
2+
3+
const expect = require('expect.js')
4+
const net = require('net')
5+
6+
describe('releasing clients', () => {
7+
it('removes a client which cannot be queried', async () => {
8+
// make a pool w/ only 1 client
9+
const pool = new Pool({ max: 1 })
10+
expect(pool.totalCount).to.eql(0)
11+
const client = await pool.connect()
12+
expect(pool.totalCount).to.eql(1)
13+
expect(pool.idleCount).to.eql(0)
14+
// reach into the client and sever its connection
15+
client.connection.end()
16+
17+
// wait for the client to error out
18+
const err = await new Promise((resolve) => client.once('error', resolve))
19+
expect(err).to.be.ok()
20+
expect(pool.totalCount).to.eql(1)
21+
expect(pool.idleCount).to.eql(0)
22+
23+
// try to return it to the pool - this removes it because its broken
24+
client.release()
25+
expect(pool.totalCount).to.eql(0)
26+
expect(pool.idleCount).to.eql(0)
27+
28+
// make sure pool still works
29+
const { rows } = await pool.query('SELECT NOW()')
30+
expect(rows).to.have.length(1)
31+
await pool.end()
32+
})
33+
34+
it('removes a client which is ending', async () => {
35+
// make a pool w/ only 1 client
36+
const pool = new Pool({ max: 1 })
37+
expect(pool.totalCount).to.eql(0)
38+
const client = await pool.connect()
39+
expect(pool.totalCount).to.eql(1)
40+
expect(pool.idleCount).to.eql(0)
41+
// end the client gracefully (but you shouldn't do this with pooled clients)
42+
client.end()
43+
44+
// try to return it to the pool
45+
client.release()
46+
expect(pool.totalCount).to.eql(0)
47+
expect(pool.idleCount).to.eql(0)
48+
49+
// make sure pool still works
50+
const { rows } = await pool.query('SELECT NOW()')
51+
expect(rows).to.have.length(1)
52+
await pool.end()
53+
})
54+
})

packages/pg-query-stream/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class PgQueryStream extends Readable {
1515
this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor)
1616
this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor)
1717
this.handleError = this.cursor.handleError.bind(this.cursor)
18+
this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor)
1819
}
1920

2021
submit(connection) {

packages/pg-query-stream/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-query-stream",
3-
"version": "3.0.0",
3+
"version": "3.0.3",
44
"description": "Postgres query result returned as readable stream",
55
"main": "index.js",
66
"scripts": {
@@ -27,12 +27,12 @@
2727
"concat-stream": "~1.0.1",
2828
"eslint-plugin-promise": "^3.5.0",
2929
"mocha": "^6.2.2",
30-
"pg": "^7.17.1",
30+
"pg": "^7.18.2",
3131
"stream-spec": "~0.3.5",
3232
"stream-tester": "0.0.5",
3333
"through": "~2.3.4"
3434
},
3535
"dependencies": {
36-
"pg-cursor": "^2.1.3"
36+
"pg-cursor": "^2.1.6"
3737
}
3838
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const assert = require('assert')
2+
const helper = require('./helper')
3+
const QueryStream = require('../')
4+
5+
helper('empty-query', function (client) {
6+
it('handles empty query', function(done) {
7+
const stream = new QueryStream('-- this is a comment', [])
8+
const query = client.query(stream)
9+
query.on('end', function () {
10+
// nothing should happen for empty query
11+
done();
12+
}).on('data', function () {
13+
// noop to kick off reading
14+
})
15+
})
16+
17+
it('continues to function after stream', function (done) {
18+
client.query('SELECT NOW()', done)
19+
})
20+
})

packages/pg/README.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,21 @@ When you open an issue please provide:
4444

4545
You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter.
4646

47-
### Sponsorship :star:
47+
## Sponsorship :two_hearts:
4848

49-
[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development.
49+
node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors:
5050

51-
Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md).
51+
<div align="center">
52+
<a href="https://www.timescale.com" target="_blank">
53+
<img height="80" src="https://node-postgres.com/timescale.svg" />
54+
</a>
55+
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAQAAAB0m0auAAAADElEQVR42mNkIBIAAABSAAI2VLqiAAAAAElFTkSuQmCC" />
56+
<a href="https://crate.io" target="_blank">
57+
<img height="80" src="https://node-postgres.com/crate-io.png" />
58+
</a>
59+
</div>
60+
61+
If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development.
5262

5363

5464
## Contributing

packages/pg/lib/client.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,16 @@ Client.prototype.query = function (config, values, callback) {
554554
Client.prototype.end = function (cb) {
555555
this._ending = true
556556

557-
if (this.activeQuery) {
557+
// if we have never connected, then end is a noop, callback immediately
558+
if (this.connection.stream.readyState === 'closed') {
559+
if (cb) {
560+
cb()
561+
} else {
562+
return this._Promise.resolve()
563+
}
564+
}
565+
566+
if (this.activeQuery || !this._queryable) {
558567
// if we have an active query we need to force a disconnect
559568
// on the socket - otherwise a hung query could block end forever
560569
this.connection.stream.destroy()

packages/pg/lib/connection.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,13 @@ Connection.prototype.connect = function (port, host) {
8383
this.stream.once('data', function (buffer) {
8484
var responseCode = buffer.toString('utf8')
8585
switch (responseCode) {
86-
case 'N': // Server does not support SSL connections
87-
return self.emit('error', new Error('The server does not support SSL connections'))
8886
case 'S': // Server supports SSL connections, continue with a secure connection
8987
break
88+
case 'N': // Server does not support SSL connections
89+
self.stream.end()
90+
return self.emit('error', new Error('The server does not support SSL connections'))
9091
default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error
92+
self.stream.end()
9193
return self.emit('error', new Error('There was an error establishing an SSL connection'))
9294
}
9395
var tls = require('tls')
@@ -98,9 +100,8 @@ Connection.prototype.connect = function (port, host) {
98100
options.servername = host
99101
}
100102
self.stream = tls.connect(options)
101-
self.attachListeners(self.stream)
102103
self.stream.on('error', reportStreamError)
103-
104+
self.attachListeners(self.stream)
104105
self.emit('sslconnect')
105106
})
106107
}
@@ -331,6 +332,10 @@ Connection.prototype.end = function () {
331332
// 0x58 = 'X'
332333
this.writer.add(emptyBuffer)
333334
this._ending = true
335+
if (!this.stream.writable) {
336+
this.stream.end()
337+
return
338+
}
334339
return this.stream.write(END_BUFFER, () => {
335340
this.stream.end()
336341
})

packages/pg/lib/native/client.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ Client.prototype._connect = function (cb) {
9797
this.connectionParameters.getLibpqConnectionString(function (err, conString) {
9898
if (err) return cb(err)
9999
self.native.connect(conString, function (err) {
100-
if (err) return cb(err)
100+
if (err) {
101+
self.native.end()
102+
return cb(err)
103+
}
101104

102105
// set internal states to connected
103106
self._connected = true

packages/pg/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg",
3-
"version": "7.17.1",
3+
"version": "7.18.2",
44
"description": "PostgreSQL client - pure javascript & libpq with the same API",
55
"keywords": [
66
"database",
@@ -23,7 +23,7 @@
2323
"packet-reader": "1.0.0",
2424
"pg-connection-string": "0.1.3",
2525
"pg-packet-stream": "^1.1.0",
26-
"pg-pool": "^2.0.9",
26+
"pg-pool": "^2.0.10",
2727
"pg-types": "^2.1.0",
2828
"pgpass": "1.x",
2929
"semver": "4.3.2"

0 commit comments

Comments
 (0)