pg 7.17.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +14 -4
- package/lib/client.js +20 -2
- package/lib/connection-fast.js +3 -12
- package/lib/connection-parameters.js +15 -1
- package/lib/connection.js +16 -20
- package/lib/defaults.js +1 -1
- package/lib/index.js +25 -25
- package/lib/native/client.js +13 -2
- package/lib/query.js +184 -190
- package/package.json +5 -5
- package/lib/compat/check-constructor.js +0 -22
- package/lib/compat/warn-deprecation.js +0 -19
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -44,11 +44,21 @@ When you open an issue please provide:
|
|
|
44
44
|
|
|
45
45
|
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.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
## Sponsorship :two_hearts:
|
|
48
48
|
|
|
49
|
-
|
|
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:
|
|
50
50
|
|
|
51
|
-
|
|
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.
|
|
52
62
|
|
|
53
63
|
|
|
54
64
|
## Contributing
|
|
@@ -69,7 +79,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask
|
|
|
69
79
|
|
|
70
80
|
## License
|
|
71
81
|
|
|
72
|
-
Copyright (c) 2010-
|
|
82
|
+
Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
|
|
73
83
|
|
|
74
84
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
75
85
|
of this software and associated documentation files (the "Software"), to deal
|
package/lib/client.js
CHANGED
|
@@ -30,7 +30,16 @@ var Client = function (config) {
|
|
|
30
30
|
this.database = this.connectionParameters.database
|
|
31
31
|
this.port = this.connectionParameters.port
|
|
32
32
|
this.host = this.connectionParameters.host
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
// "hiding" the password so it doesn't show up in stack traces
|
|
35
|
+
// or if the client is console.logged
|
|
36
|
+
Object.defineProperty(this, 'password', {
|
|
37
|
+
configurable: true,
|
|
38
|
+
enumerable: false,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: this.connectionParameters.password
|
|
41
|
+
})
|
|
42
|
+
|
|
34
43
|
this.replication = this.connectionParameters.replication
|
|
35
44
|
|
|
36
45
|
var c = config || {}
|
|
@@ -545,7 +554,16 @@ Client.prototype.query = function (config, values, callback) {
|
|
|
545
554
|
Client.prototype.end = function (cb) {
|
|
546
555
|
this._ending = true
|
|
547
556
|
|
|
548
|
-
if
|
|
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) {
|
|
549
567
|
// if we have an active query we need to force a disconnect
|
|
550
568
|
// on the socket - otherwise a hung query could block end forever
|
|
551
569
|
this.connection.stream.destroy()
|
package/lib/connection-fast.js
CHANGED
|
@@ -93,18 +93,9 @@ Connection.prototype.connect = function (port, host) {
|
|
|
93
93
|
return self.emit('error', new Error('There was an error establishing an SSL connection'))
|
|
94
94
|
}
|
|
95
95
|
var tls = require('tls')
|
|
96
|
-
const options = {
|
|
97
|
-
socket: self.stream
|
|
98
|
-
|
|
99
|
-
rejectUnauthorized: self.ssl.rejectUnauthorized,
|
|
100
|
-
ca: self.ssl.ca,
|
|
101
|
-
pfx: self.ssl.pfx,
|
|
102
|
-
key: self.ssl.key,
|
|
103
|
-
passphrase: self.ssl.passphrase,
|
|
104
|
-
cert: self.ssl.cert,
|
|
105
|
-
secureOptions: self.ssl.secureOptions,
|
|
106
|
-
NPNProtocols: self.ssl.NPNProtocols
|
|
107
|
-
}
|
|
96
|
+
const options = Object.assign({
|
|
97
|
+
socket: self.stream
|
|
98
|
+
}, self.ssl)
|
|
108
99
|
if (net.isIP(host) === 0) {
|
|
109
100
|
options.servername = host
|
|
110
101
|
}
|
|
@@ -52,9 +52,23 @@ var ConnectionParameters = function (config) {
|
|
|
52
52
|
|
|
53
53
|
this.user = val('user', config)
|
|
54
54
|
this.database = val('database', config)
|
|
55
|
+
|
|
56
|
+
if (this.database === undefined) {
|
|
57
|
+
this.database = this.user
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
this.port = parseInt(val('port', config), 10)
|
|
56
61
|
this.host = val('host', config)
|
|
57
|
-
|
|
62
|
+
|
|
63
|
+
// "hiding" the password so it doesn't show up in stack traces
|
|
64
|
+
// or if the client is console.logged
|
|
65
|
+
Object.defineProperty(this, 'password', {
|
|
66
|
+
configurable: true,
|
|
67
|
+
enumerable: false,
|
|
68
|
+
writable: true,
|
|
69
|
+
value: val('password', config)
|
|
70
|
+
})
|
|
71
|
+
|
|
58
72
|
this.binary = val('binary', config)
|
|
59
73
|
this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl
|
|
60
74
|
this.client_encoding = val('client_encoding', config)
|
package/lib/connection.js
CHANGED
|
@@ -83,33 +83,25 @@ Connection.prototype.connect = function (port, host) {
|
|
|
83
83
|
this.stream.once('data', function (buffer) {
|
|
84
84
|
var responseCode = buffer.toString('utf8')
|
|
85
85
|
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'))
|
|
88
86
|
case 'S': // Server supports SSL connections, continue with a secure connection
|
|
89
87
|
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'))
|
|
90
91
|
default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error
|
|
92
|
+
self.stream.end()
|
|
91
93
|
return self.emit('error', new Error('There was an error establishing an SSL connection'))
|
|
92
94
|
}
|
|
93
95
|
var tls = require('tls')
|
|
94
|
-
const options = {
|
|
95
|
-
socket: self.stream
|
|
96
|
-
|
|
97
|
-
rejectUnauthorized: self.ssl.rejectUnauthorized,
|
|
98
|
-
ca: self.ssl.ca,
|
|
99
|
-
pfx: self.ssl.pfx,
|
|
100
|
-
key: self.ssl.key,
|
|
101
|
-
passphrase: self.ssl.passphrase,
|
|
102
|
-
cert: self.ssl.cert,
|
|
103
|
-
secureOptions: self.ssl.secureOptions,
|
|
104
|
-
NPNProtocols: self.ssl.NPNProtocols
|
|
105
|
-
}
|
|
96
|
+
const options = Object.assign({
|
|
97
|
+
socket: self.stream
|
|
98
|
+
}, self.ssl)
|
|
106
99
|
if (net.isIP(host) === 0) {
|
|
107
100
|
options.servername = host
|
|
108
101
|
}
|
|
109
102
|
self.stream = tls.connect(options)
|
|
110
|
-
self.attachListeners(self.stream)
|
|
111
103
|
self.stream.on('error', reportStreamError)
|
|
112
|
-
|
|
104
|
+
self.attachListeners(self.stream)
|
|
113
105
|
self.emit('sslconnect')
|
|
114
106
|
})
|
|
115
107
|
}
|
|
@@ -340,6 +332,10 @@ Connection.prototype.end = function () {
|
|
|
340
332
|
// 0x58 = 'X'
|
|
341
333
|
this.writer.add(emptyBuffer)
|
|
342
334
|
this._ending = true
|
|
335
|
+
if (!this.stream.writable) {
|
|
336
|
+
this.stream.end()
|
|
337
|
+
return
|
|
338
|
+
}
|
|
343
339
|
return this.stream.write(END_BUFFER, () => {
|
|
344
340
|
this.stream.end()
|
|
345
341
|
})
|
|
@@ -592,7 +588,7 @@ Connection.prototype._readValue = function (buffer) {
|
|
|
592
588
|
}
|
|
593
589
|
|
|
594
590
|
// parses error
|
|
595
|
-
Connection.prototype.parseE = function (buffer, length) {
|
|
591
|
+
Connection.prototype.parseE = function (buffer, length, isNotice) {
|
|
596
592
|
var fields = {}
|
|
597
593
|
var fieldType = this.readString(buffer, 1)
|
|
598
594
|
while (fieldType !== '\0') {
|
|
@@ -601,10 +597,10 @@ Connection.prototype.parseE = function (buffer, length) {
|
|
|
601
597
|
}
|
|
602
598
|
|
|
603
599
|
// the msg is an Error instance
|
|
604
|
-
var msg = new Error(fields.M)
|
|
600
|
+
var msg = isNotice ? { message: fields.M } : new Error(fields.M)
|
|
605
601
|
|
|
606
602
|
// for compatibility with Message
|
|
607
|
-
msg.name = 'error'
|
|
603
|
+
msg.name = isNotice ? 'notice' : 'error'
|
|
608
604
|
msg.length = length
|
|
609
605
|
|
|
610
606
|
msg.severity = fields.S
|
|
@@ -628,7 +624,7 @@ Connection.prototype.parseE = function (buffer, length) {
|
|
|
628
624
|
|
|
629
625
|
// same thing, different name
|
|
630
626
|
Connection.prototype.parseN = function (buffer, length) {
|
|
631
|
-
var msg = this.parseE(buffer, length)
|
|
627
|
+
var msg = this.parseE(buffer, length, true)
|
|
632
628
|
msg.name = 'notice'
|
|
633
629
|
return msg
|
|
634
630
|
}
|
package/lib/defaults.js
CHANGED
|
@@ -15,7 +15,7 @@ module.exports = {
|
|
|
15
15
|
user: process.platform === 'win32' ? process.env.USERNAME : process.env.USER,
|
|
16
16
|
|
|
17
17
|
// name of database to connect
|
|
18
|
-
database:
|
|
18
|
+
database: undefined,
|
|
19
19
|
|
|
20
20
|
// database user's password
|
|
21
21
|
password: null,
|
package/lib/index.js
CHANGED
|
@@ -7,25 +7,17 @@
|
|
|
7
7
|
* README.md file in the root directory of this source tree.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
var util = require('util')
|
|
11
10
|
var Client = require('./client')
|
|
12
11
|
var defaults = require('./defaults')
|
|
13
12
|
var Connection = require('./connection')
|
|
14
13
|
var Pool = require('pg-pool')
|
|
15
|
-
const checkConstructor = require('./compat/check-constructor')
|
|
16
14
|
|
|
17
15
|
const poolFactory = (Client) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
var config = Object.assign({ Client: Client }, options)
|
|
23
|
-
return new Pool(config)
|
|
16
|
+
return class BoundPool extends Pool {
|
|
17
|
+
constructor (options) {
|
|
18
|
+
super(options, Client)
|
|
19
|
+
}
|
|
24
20
|
}
|
|
25
|
-
|
|
26
|
-
util.inherits(BoundPool, Pool)
|
|
27
|
-
|
|
28
|
-
return BoundPool
|
|
29
21
|
}
|
|
30
22
|
|
|
31
23
|
var PG = function (clientConstructor) {
|
|
@@ -44,20 +36,28 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') {
|
|
|
44
36
|
module.exports = new PG(Client)
|
|
45
37
|
|
|
46
38
|
// lazy require native module...the native module may not have installed
|
|
47
|
-
module.exports
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
native =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
Object.defineProperty(module.exports, 'native', {
|
|
40
|
+
configurable: true,
|
|
41
|
+
enumerable: false,
|
|
42
|
+
get() {
|
|
43
|
+
var native = null
|
|
44
|
+
try {
|
|
45
|
+
native = new PG(require('./native'))
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (err.code !== 'MODULE_NOT_FOUND') {
|
|
48
|
+
throw err
|
|
49
|
+
}
|
|
50
|
+
/* eslint-disable no-console */
|
|
51
|
+
console.error(err.message)
|
|
52
|
+
/* eslint-enable no-console */
|
|
55
53
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
|
|
55
|
+
// overwrite module.exports.native so that getter is never called again
|
|
56
|
+
Object.defineProperty(module.exports, 'native', {
|
|
57
|
+
value: native
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return native
|
|
59
61
|
}
|
|
60
|
-
module.exports.native = native
|
|
61
|
-
return native
|
|
62
62
|
})
|
|
63
63
|
}
|
package/lib/native/client.js
CHANGED
|
@@ -43,7 +43,15 @@ var Client = module.exports = function (config) {
|
|
|
43
43
|
// for the time being. TODO: deprecate all this jazz
|
|
44
44
|
var cp = this.connectionParameters = new ConnectionParameters(config)
|
|
45
45
|
this.user = cp.user
|
|
46
|
-
|
|
46
|
+
|
|
47
|
+
// "hiding" the password so it doesn't show up in stack traces
|
|
48
|
+
// or if the client is console.logged
|
|
49
|
+
Object.defineProperty(this, 'password', {
|
|
50
|
+
configurable: true,
|
|
51
|
+
enumerable: false,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: cp.password
|
|
54
|
+
})
|
|
47
55
|
this.database = cp.database
|
|
48
56
|
this.host = cp.host
|
|
49
57
|
this.port = cp.port
|
|
@@ -89,7 +97,10 @@ Client.prototype._connect = function (cb) {
|
|
|
89
97
|
this.connectionParameters.getLibpqConnectionString(function (err, conString) {
|
|
90
98
|
if (err) return cb(err)
|
|
91
99
|
self.native.connect(conString, function (err) {
|
|
92
|
-
if (err)
|
|
100
|
+
if (err) {
|
|
101
|
+
self.native.end()
|
|
102
|
+
return cb(err)
|
|
103
|
+
}
|
|
93
104
|
|
|
94
105
|
// set internal states to connected
|
|
95
106
|
self._connected = true
|
package/lib/query.js
CHANGED
|
@@ -7,226 +7,220 @@
|
|
|
7
7
|
* README.md file in the root directory of this source tree.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.callback = config.callback
|
|
34
|
-
this._rowMode = config.rowMode
|
|
35
|
-
if (process.domain && config.callback) {
|
|
36
|
-
this.callback = process.domain.bind(config.callback)
|
|
37
|
-
}
|
|
38
|
-
this._result = new Result(this._rowMode, this.types)
|
|
39
|
-
|
|
40
|
-
// potential for multiple results
|
|
41
|
-
this._results = this._result
|
|
42
|
-
this.isPreparedStatement = false
|
|
43
|
-
this._canceledDueToError = false
|
|
44
|
-
this._promise = null
|
|
45
|
-
EventEmitter.call(this)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
util.inherits(Query, EventEmitter)
|
|
49
|
-
|
|
50
|
-
Query.prototype.requiresPreparation = function () {
|
|
51
|
-
// named queries must always be prepared
|
|
52
|
-
if (this.name) { return true }
|
|
53
|
-
// always prepare if there are max number of rows expected per
|
|
54
|
-
// portal execution
|
|
55
|
-
if (this.rows) { return true }
|
|
56
|
-
// don't prepare empty text queries
|
|
57
|
-
if (!this.text) { return false }
|
|
58
|
-
// prepare if there are values
|
|
59
|
-
if (!this.values) { return false }
|
|
60
|
-
return this.values.length > 0
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Query.prototype._checkForMultirow = function () {
|
|
64
|
-
// if we already have a result with a command property
|
|
65
|
-
// then we've already executed one query in a multi-statement simple query
|
|
66
|
-
// turn our results into an array of results
|
|
67
|
-
if (this._result.command) {
|
|
68
|
-
if (!Array.isArray(this._results)) {
|
|
69
|
-
this._results = [this._result]
|
|
10
|
+
const { EventEmitter } = require('events')
|
|
11
|
+
|
|
12
|
+
const Result = require('./result')
|
|
13
|
+
const utils = require('./utils')
|
|
14
|
+
|
|
15
|
+
class Query extends EventEmitter {
|
|
16
|
+
constructor(config, values, callback) {
|
|
17
|
+
super()
|
|
18
|
+
|
|
19
|
+
config = utils.normalizeQueryConfig(config, values, callback)
|
|
20
|
+
|
|
21
|
+
this.text = config.text
|
|
22
|
+
this.values = config.values
|
|
23
|
+
this.rows = config.rows
|
|
24
|
+
this.types = config.types
|
|
25
|
+
this.name = config.name
|
|
26
|
+
this.binary = config.binary
|
|
27
|
+
// use unique portal name each time
|
|
28
|
+
this.portal = config.portal || ''
|
|
29
|
+
this.callback = config.callback
|
|
30
|
+
this._rowMode = config.rowMode
|
|
31
|
+
if (process.domain && config.callback) {
|
|
32
|
+
this.callback = process.domain.bind(config.callback)
|
|
70
33
|
}
|
|
71
34
|
this._result = new Result(this._rowMode, this.types)
|
|
72
|
-
|
|
35
|
+
|
|
36
|
+
// potential for multiple results
|
|
37
|
+
this._results = this._result
|
|
38
|
+
this.isPreparedStatement = false
|
|
39
|
+
this._canceledDueToError = false
|
|
40
|
+
this._promise = null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
requiresPreparation() {
|
|
44
|
+
// named queries must always be prepared
|
|
45
|
+
if (this.name) { return true }
|
|
46
|
+
// always prepare if there are max number of rows expected per
|
|
47
|
+
// portal execution
|
|
48
|
+
if (this.rows) { return true }
|
|
49
|
+
// don't prepare empty text queries
|
|
50
|
+
if (!this.text) { return false }
|
|
51
|
+
// prepare if there are values
|
|
52
|
+
if (!this.values) { return false }
|
|
53
|
+
return this.values.length > 0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_checkForMultirow() {
|
|
57
|
+
// if we already have a result with a command property
|
|
58
|
+
// then we've already executed one query in a multi-statement simple query
|
|
59
|
+
// turn our results into an array of results
|
|
60
|
+
if (this._result.command) {
|
|
61
|
+
if (!Array.isArray(this._results)) {
|
|
62
|
+
this._results = [this._result]
|
|
63
|
+
}
|
|
64
|
+
this._result = new Result(this._rowMode, this.types)
|
|
65
|
+
this._results.push(this._result)
|
|
66
|
+
}
|
|
73
67
|
}
|
|
74
|
-
}
|
|
75
68
|
|
|
76
|
-
// associates row metadata from the supplied
|
|
77
|
-
// message with this query object
|
|
78
|
-
// metadata used when parsing row results
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
69
|
+
// associates row metadata from the supplied
|
|
70
|
+
// message with this query object
|
|
71
|
+
// metadata used when parsing row results
|
|
72
|
+
handleRowDescription(msg) {
|
|
73
|
+
this._checkForMultirow()
|
|
74
|
+
this._result.addFields(msg.fields)
|
|
75
|
+
this._accumulateRows = this.callback || !this.listeners('row').length
|
|
76
|
+
}
|
|
84
77
|
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
handleDataRow(msg) {
|
|
79
|
+
let row
|
|
87
80
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
if (this._canceledDueToError) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
91
84
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
85
|
+
try {
|
|
86
|
+
row = this._result.parseRow(msg.fields)
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this._canceledDueToError = err
|
|
89
|
+
return
|
|
90
|
+
}
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
this.emit('row', row, this._result)
|
|
93
|
+
if (this._accumulateRows) {
|
|
94
|
+
this._result.addRow(row)
|
|
95
|
+
}
|
|
102
96
|
}
|
|
103
|
-
}
|
|
104
97
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
98
|
+
handleCommandComplete(msg, con) {
|
|
99
|
+
this._checkForMultirow()
|
|
100
|
+
this._result.addCommandComplete(msg)
|
|
101
|
+
// need to sync after each command complete of a prepared statement
|
|
102
|
+
if (this.isPreparedStatement) {
|
|
103
|
+
con.sync()
|
|
104
|
+
}
|
|
111
105
|
}
|
|
112
|
-
}
|
|
113
106
|
|
|
114
|
-
// if a named prepared statement is created with empty query text
|
|
115
|
-
// the backend will send an emptyQuery message but *not* a command complete message
|
|
116
|
-
// execution on the connection will hang until the backend receives a sync message
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
// if a named prepared statement is created with empty query text
|
|
108
|
+
// the backend will send an emptyQuery message but *not* a command complete message
|
|
109
|
+
// execution on the connection will hang until the backend receives a sync message
|
|
110
|
+
handleEmptyQuery(con) {
|
|
111
|
+
if (this.isPreparedStatement) {
|
|
112
|
+
con.sync()
|
|
113
|
+
}
|
|
120
114
|
}
|
|
121
|
-
}
|
|
122
115
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
116
|
+
handleReadyForQuery(con) {
|
|
117
|
+
if (this._canceledDueToError) {
|
|
118
|
+
return this.handleError(this._canceledDueToError, con)
|
|
119
|
+
}
|
|
120
|
+
if (this.callback) {
|
|
121
|
+
this.callback(null, this._results)
|
|
122
|
+
}
|
|
123
|
+
this.emit('end', this._results)
|
|
129
124
|
}
|
|
130
|
-
this.emit('end', this._results)
|
|
131
|
-
}
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
126
|
+
handleError(err, connection) {
|
|
127
|
+
// need to sync after error during a prepared statement
|
|
128
|
+
if (this.isPreparedStatement) {
|
|
129
|
+
connection.sync()
|
|
130
|
+
}
|
|
131
|
+
if (this._canceledDueToError) {
|
|
132
|
+
err = this._canceledDueToError
|
|
133
|
+
this._canceledDueToError = false
|
|
134
|
+
}
|
|
135
|
+
// if callback supplied do not emit error event as uncaught error
|
|
136
|
+
// events will bubble up to node process
|
|
137
|
+
if (this.callback) {
|
|
138
|
+
return this.callback(err)
|
|
139
|
+
}
|
|
140
|
+
this.emit('error', err)
|
|
146
141
|
}
|
|
147
|
-
this.emit('error', err)
|
|
148
|
-
}
|
|
149
142
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
143
|
+
submit(connection) {
|
|
144
|
+
if (typeof this.text !== 'string' && typeof this.name !== 'string') {
|
|
145
|
+
return new Error('A query must have either text or a name. Supplying neither is unsupported.')
|
|
146
|
+
}
|
|
147
|
+
const previous = connection.parsedStatements[this.name]
|
|
148
|
+
if (this.text && previous && this.text !== previous) {
|
|
149
|
+
return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
|
|
150
|
+
}
|
|
151
|
+
if (this.values && !Array.isArray(this.values)) {
|
|
152
|
+
return new Error('Query values must be an array')
|
|
153
|
+
}
|
|
154
|
+
if (this.requiresPreparation()) {
|
|
155
|
+
this.prepare(connection)
|
|
156
|
+
} else {
|
|
157
|
+
connection.query(this.text)
|
|
158
|
+
}
|
|
159
|
+
return null
|
|
157
160
|
}
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
|
|
162
|
+
hasBeenParsed(connection) {
|
|
163
|
+
return this.name && connection.parsedStatements[this.name]
|
|
160
164
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
connection.query(this.text)
|
|
165
|
+
|
|
166
|
+
handlePortalSuspended(connection) {
|
|
167
|
+
this._getRows(connection, this.rows)
|
|
165
168
|
}
|
|
166
|
-
return null
|
|
167
|
-
}
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
_getRows(connection, rows) {
|
|
171
|
+
connection.execute({
|
|
172
|
+
portal: this.portal,
|
|
173
|
+
rows: rows
|
|
174
|
+
}, true)
|
|
175
|
+
connection.flush()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
prepare(connection) {
|
|
179
|
+
// prepared statements need sync to be called after each command
|
|
180
|
+
// complete or when an error is encountered
|
|
181
|
+
this.isPreparedStatement = true
|
|
182
|
+
// TODO refactor this poor encapsulation
|
|
183
|
+
if (!this.hasBeenParsed(connection)) {
|
|
184
|
+
connection.parse({
|
|
185
|
+
text: this.text,
|
|
186
|
+
name: this.name,
|
|
187
|
+
types: this.types
|
|
188
|
+
}, true)
|
|
189
|
+
}
|
|
172
190
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
if (this.values) {
|
|
192
|
+
try {
|
|
193
|
+
this.values = this.values.map(utils.prepareValue)
|
|
194
|
+
} catch (err) {
|
|
195
|
+
this.handleError(err, connection)
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
}
|
|
176
199
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
200
|
+
// http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
|
|
201
|
+
connection.bind({
|
|
202
|
+
portal: this.portal,
|
|
203
|
+
statement: this.name,
|
|
204
|
+
values: this.values,
|
|
205
|
+
binary: this.binary
|
|
206
|
+
}, true)
|
|
184
207
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// complete or when an error is encountered
|
|
189
|
-
this.isPreparedStatement = true
|
|
190
|
-
// TODO refactor this poor encapsulation
|
|
191
|
-
if (!this.hasBeenParsed(connection)) {
|
|
192
|
-
connection.parse({
|
|
193
|
-
text: self.text,
|
|
194
|
-
name: self.name,
|
|
195
|
-
types: self.types
|
|
208
|
+
connection.describe({
|
|
209
|
+
type: 'P',
|
|
210
|
+
name: this.portal || ''
|
|
196
211
|
}, true)
|
|
197
|
-
}
|
|
198
212
|
|
|
199
|
-
|
|
200
|
-
try {
|
|
201
|
-
self.values = self.values.map(utils.prepareValue)
|
|
202
|
-
} catch (err) {
|
|
203
|
-
this.handleError(err, connection)
|
|
204
|
-
return
|
|
205
|
-
}
|
|
213
|
+
this._getRows(connection, this.rows)
|
|
206
214
|
}
|
|
207
215
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
statement: self.name,
|
|
212
|
-
values: self.values,
|
|
213
|
-
binary: self.binary
|
|
214
|
-
}, true)
|
|
215
|
-
|
|
216
|
-
connection.describe({
|
|
217
|
-
type: 'P',
|
|
218
|
-
name: self.portal || ''
|
|
219
|
-
}, true)
|
|
220
|
-
|
|
221
|
-
this._getRows(connection, this.rows)
|
|
222
|
-
}
|
|
216
|
+
handleCopyInResponse(connection) {
|
|
217
|
+
connection.sendCopyFail('No source stream defined')
|
|
218
|
+
}
|
|
223
219
|
|
|
224
|
-
|
|
225
|
-
|
|
220
|
+
// eslint-disable-next-line no-unused-vars
|
|
221
|
+
handleCopyData(msg, connection) {
|
|
222
|
+
// noop
|
|
223
|
+
}
|
|
226
224
|
}
|
|
227
225
|
|
|
228
|
-
// eslint-disable-next-line no-unused-vars
|
|
229
|
-
Query.prototype.handleCopyData = function (msg, connection) {
|
|
230
|
-
// noop
|
|
231
|
-
}
|
|
232
226
|
module.exports = Query
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "PostgreSQL client - pure javascript & libpq with the same API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"postgresql",
|
|
12
12
|
"rdbms"
|
|
13
13
|
],
|
|
14
|
-
"homepage": "
|
|
14
|
+
"homepage": "https://github.com/brianc/node-postgres",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git://github.com/brianc/node-postgres.git"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"packet-reader": "1.0.0",
|
|
24
24
|
"pg-connection-string": "0.1.3",
|
|
25
25
|
"pg-packet-stream": "^1.1.0",
|
|
26
|
-
"pg-pool": "^
|
|
26
|
+
"pg-pool": "^3.0.0",
|
|
27
27
|
"pg-types": "^2.1.0",
|
|
28
28
|
"pgpass": "1.x",
|
|
29
29
|
"semver": "4.3.2"
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
],
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"engines": {
|
|
54
|
-
"node": ">=
|
|
54
|
+
"node": ">= 8.0.0"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "a227d3e8d47e1eb53296a3a013f2e7514cd152c3"
|
|
57
57
|
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const warnDeprecation = require('./warn-deprecation')
|
|
4
|
-
|
|
5
|
-
// Node 4 doesn’t support new.target.
|
|
6
|
-
let hasNewTarget
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
// eslint-disable-next-line no-eval
|
|
10
|
-
eval('(function () { new.target })')
|
|
11
|
-
hasNewTarget = true
|
|
12
|
-
} catch (error) {
|
|
13
|
-
hasNewTarget = false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const checkConstructor = (name, code, getNewTarget) => {
|
|
17
|
-
if (hasNewTarget && getNewTarget() === undefined) {
|
|
18
|
-
warnDeprecation(`Constructing a ${name} without new is deprecated and will stop working in pg 8.`, code)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
module.exports = checkConstructor
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const util = require('util')
|
|
4
|
-
|
|
5
|
-
const dummyFunctions = new Map()
|
|
6
|
-
|
|
7
|
-
// Node 4 doesn’t support process.emitWarning(message, 'DeprecationWarning', code).
|
|
8
|
-
const emitDeprecationWarning = (message, code) => {
|
|
9
|
-
let dummy = dummyFunctions.get(code)
|
|
10
|
-
|
|
11
|
-
if (dummy === undefined) {
|
|
12
|
-
dummy = util.deprecate(() => {}, message)
|
|
13
|
-
dummyFunctions.set(code, dummy)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
dummy()
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
module.exports = emitDeprecationWarning
|