pg 8.1.0 → 8.3.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/README.md +34 -39
- package/lib/client.js +3 -3
- package/lib/connection-parameters.js +2 -0
- package/lib/connection.js +44 -507
- package/lib/defaults.js +2 -0
- package/package.json +5 -6
- package/LICENSE +0 -21
- package/lib/connection-fast.js +0 -214
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<span class="badge-npmversion"><a href="https://npmjs.org/package/pg" title="View this project on NPM"><img src="https://img.shields.io/npm/v/pg.svg" alt="NPM version" /></a></span>
|
|
6
6
|
<span class="badge-npmdownloads"><a href="https://npmjs.org/package/pg" title="View this project on NPM"><img src="https://img.shields.io/npm/dm/pg.svg" alt="NPM downloads" /></a></span>
|
|
7
7
|
|
|
8
|
-
Non-blocking PostgreSQL client for Node.js.
|
|
8
|
+
Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -14,30 +14,31 @@ $ npm install pg
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
---
|
|
17
|
-
## :star: [Documentation](https://node-postgres.com) :star:
|
|
18
17
|
|
|
18
|
+
## :star: [Documentation](https://node-postgres.com) :star:
|
|
19
19
|
|
|
20
20
|
### Features
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
- Pure JavaScript client and native libpq bindings share _the same API_
|
|
23
|
+
- Connection pooling
|
|
24
|
+
- Extensible JS ↔ PostgreSQL data-type coercion
|
|
25
|
+
- Supported PostgreSQL features
|
|
26
|
+
- Parameterized queries
|
|
27
|
+
- Named statements with query plan caching
|
|
28
|
+
- Async notifications with `LISTEN/NOTIFY`
|
|
29
|
+
- Bulk import & export with `COPY TO/COPY FROM`
|
|
30
30
|
|
|
31
31
|
### Extras
|
|
32
32
|
|
|
33
|
-
node-postgres is by design pretty light on abstractions.
|
|
33
|
+
node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture.
|
|
34
34
|
The entire list can be found on our [wiki](https://github.com/brianc/node-postgres/wiki/Extras).
|
|
35
35
|
|
|
36
36
|
## Support
|
|
37
37
|
|
|
38
|
-
node-postgres is free software.
|
|
38
|
+
node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better!
|
|
39
39
|
|
|
40
40
|
When you open an issue please provide:
|
|
41
|
+
|
|
41
42
|
- version of Node
|
|
42
43
|
- version of Postgres
|
|
43
44
|
- smallest possible snippet of code to reproduce the problem
|
|
@@ -49,10 +50,6 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that
|
|
|
49
50
|
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
51
|
|
|
51
52
|
<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
53
|
<a href="https://crate.io" target="_blank">
|
|
57
54
|
<img height="80" src="https://node-postgres.com/crate-io.png" />
|
|
58
55
|
</a>
|
|
@@ -60,19 +57,18 @@ node-postgres's continued development has been made possible in part by generous
|
|
|
60
57
|
|
|
61
58
|
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.
|
|
62
59
|
|
|
63
|
-
|
|
64
60
|
## Contributing
|
|
65
61
|
|
|
66
|
-
|
|
62
|
+
**:heart: contributions!**
|
|
67
63
|
|
|
68
|
-
I will
|
|
69
|
-
|
|
64
|
+
I will **happily** accept your pull request if it:
|
|
65
|
+
|
|
66
|
+
- **has tests**
|
|
70
67
|
- looks reasonable
|
|
71
68
|
- does not break backwards compatibility
|
|
72
69
|
|
|
73
70
|
If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require.
|
|
74
71
|
|
|
75
|
-
|
|
76
72
|
## Troubleshooting and FAQ
|
|
77
73
|
|
|
78
74
|
The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ)
|
|
@@ -81,21 +77,20 @@ The causes and solutions to common errors can be found among the [Frequently Ask
|
|
|
81
77
|
|
|
82
78
|
Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
80
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
81
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
82
|
+
in the Software without restriction, including without limitation the rights
|
|
83
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
84
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
85
|
+
furnished to do so, subject to the following conditions:
|
|
86
|
+
|
|
87
|
+
The above copyright notice and this permission notice shall be included in
|
|
88
|
+
all copies or substantial portions of the Software.
|
|
89
|
+
|
|
90
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
91
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
92
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
93
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
94
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
95
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
96
|
+
THE SOFTWARE.
|
package/lib/client.js
CHANGED
|
@@ -18,9 +18,6 @@ var ConnectionParameters = require('./connection-parameters')
|
|
|
18
18
|
var Query = require('./query')
|
|
19
19
|
var defaults = require('./defaults')
|
|
20
20
|
var Connection = require('./connection')
|
|
21
|
-
if (process.env.PG_FAST_CONNECTION) {
|
|
22
|
-
Connection = require('./connection-fast')
|
|
23
|
-
}
|
|
24
21
|
|
|
25
22
|
var Client = function (config) {
|
|
26
23
|
EventEmitter.call(this)
|
|
@@ -394,6 +391,9 @@ Client.prototype.getStartupConf = function () {
|
|
|
394
391
|
if (params.idle_in_transaction_session_timeout) {
|
|
395
392
|
data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10))
|
|
396
393
|
}
|
|
394
|
+
if (params.options) {
|
|
395
|
+
data.options = params.options
|
|
396
|
+
}
|
|
397
397
|
|
|
398
398
|
return data
|
|
399
399
|
}
|
|
@@ -70,6 +70,7 @@ var ConnectionParameters = function (config) {
|
|
|
70
70
|
})
|
|
71
71
|
|
|
72
72
|
this.binary = val('binary', config)
|
|
73
|
+
this.options = val('options', config)
|
|
73
74
|
|
|
74
75
|
this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl
|
|
75
76
|
|
|
@@ -126,6 +127,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) {
|
|
|
126
127
|
add(params, this, 'application_name')
|
|
127
128
|
add(params, this, 'fallback_application_name')
|
|
128
129
|
add(params, this, 'connect_timeout')
|
|
130
|
+
add(params, this, 'options')
|
|
129
131
|
|
|
130
132
|
var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {}
|
|
131
133
|
add(params, ssl, 'sslmode')
|
package/lib/connection.js
CHANGED
|
@@ -11,11 +11,9 @@ var net = require('net')
|
|
|
11
11
|
var EventEmitter = require('events').EventEmitter
|
|
12
12
|
var util = require('util')
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
var Reader = require('packet-reader')
|
|
14
|
+
const { parse, serialize } = require('pg-protocol')
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
var BINARY_MODE = 1
|
|
16
|
+
// TODO(bmc) support binary mode at some point
|
|
19
17
|
var Connection = function (config) {
|
|
20
18
|
EventEmitter.call(this)
|
|
21
19
|
config = config || {}
|
|
@@ -23,20 +21,10 @@ var Connection = function (config) {
|
|
|
23
21
|
this._keepAlive = config.keepAlive
|
|
24
22
|
this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis
|
|
25
23
|
this.lastBuffer = false
|
|
26
|
-
this.lastOffset = 0
|
|
27
|
-
this.buffer = null
|
|
28
|
-
this.offset = null
|
|
29
|
-
this.encoding = config.encoding || 'utf8'
|
|
30
24
|
this.parsedStatements = {}
|
|
31
|
-
this.writer = new Writer()
|
|
32
25
|
this.ssl = config.ssl || false
|
|
33
26
|
this._ending = false
|
|
34
|
-
this._mode = TEXT_MODE
|
|
35
27
|
this._emitMessage = false
|
|
36
|
-
this._reader = new Reader({
|
|
37
|
-
headerSize: 1,
|
|
38
|
-
lengthPadding: -4,
|
|
39
|
-
})
|
|
40
28
|
var self = this
|
|
41
29
|
this.on('newListener', function (eventName) {
|
|
42
30
|
if (eventName === 'message') {
|
|
@@ -51,6 +39,7 @@ Connection.prototype.connect = function (port, host) {
|
|
|
51
39
|
var self = this
|
|
52
40
|
|
|
53
41
|
this._connecting = true
|
|
42
|
+
this.stream.setNoDelay(true)
|
|
54
43
|
this.stream.connect(port, host)
|
|
55
44
|
|
|
56
45
|
this.stream.once('connect', function () {
|
|
@@ -101,576 +90,124 @@ Connection.prototype.connect = function (port, host) {
|
|
|
101
90
|
options.servername = host
|
|
102
91
|
}
|
|
103
92
|
self.stream = tls.connect(options)
|
|
104
|
-
self.stream.on('error', reportStreamError)
|
|
105
93
|
self.attachListeners(self.stream)
|
|
94
|
+
self.stream.on('error', reportStreamError)
|
|
95
|
+
|
|
106
96
|
self.emit('sslconnect')
|
|
107
97
|
})
|
|
108
98
|
}
|
|
109
99
|
|
|
110
100
|
Connection.prototype.attachListeners = function (stream) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
self._reader.addChunk(buff)
|
|
114
|
-
var packet = self._reader.read()
|
|
115
|
-
while (packet) {
|
|
116
|
-
var msg = self.parseMessage(packet)
|
|
117
|
-
var eventName = msg.name === 'error' ? 'errorMessage' : msg.name
|
|
118
|
-
if (self._emitMessage) {
|
|
119
|
-
self.emit('message', msg)
|
|
120
|
-
}
|
|
121
|
-
self.emit(eventName, msg)
|
|
122
|
-
packet = self._reader.read()
|
|
123
|
-
}
|
|
101
|
+
stream.on('end', () => {
|
|
102
|
+
this.emit('end')
|
|
124
103
|
})
|
|
125
|
-
stream
|
|
126
|
-
|
|
104
|
+
parse(stream, (msg) => {
|
|
105
|
+
var eventName = msg.name === 'error' ? 'errorMessage' : msg.name
|
|
106
|
+
if (this._emitMessage) {
|
|
107
|
+
this.emit('message', msg)
|
|
108
|
+
}
|
|
109
|
+
this.emit(eventName, msg)
|
|
127
110
|
})
|
|
128
111
|
}
|
|
129
112
|
|
|
130
113
|
Connection.prototype.requestSsl = function () {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
var length = bodyBuffer.length + 4
|
|
134
|
-
|
|
135
|
-
var buffer = new Writer().addInt32(length).add(bodyBuffer).join()
|
|
136
|
-
this.stream.write(buffer)
|
|
114
|
+
this.stream.write(serialize.requestSsl())
|
|
137
115
|
}
|
|
138
116
|
|
|
139
117
|
Connection.prototype.startup = function (config) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
Object.keys(config).forEach(function (key) {
|
|
143
|
-
var val = config[key]
|
|
144
|
-
writer.addCString(key).addCString(val)
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
writer.addCString('client_encoding').addCString("'utf-8'")
|
|
148
|
-
|
|
149
|
-
var bodyBuffer = writer.addCString('').flush()
|
|
150
|
-
// this message is sent without a code
|
|
151
|
-
|
|
152
|
-
var length = bodyBuffer.length + 4
|
|
153
|
-
|
|
154
|
-
var buffer = new Writer().addInt32(length).add(bodyBuffer).join()
|
|
155
|
-
this.stream.write(buffer)
|
|
118
|
+
this.stream.write(serialize.startup(config))
|
|
156
119
|
}
|
|
157
120
|
|
|
158
121
|
Connection.prototype.cancel = function (processID, secretKey) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
var length = bodyBuffer.length + 4
|
|
162
|
-
|
|
163
|
-
var buffer = new Writer().addInt32(length).add(bodyBuffer).join()
|
|
164
|
-
this.stream.write(buffer)
|
|
122
|
+
this._send(serialize.cancel(processID, secretKey))
|
|
165
123
|
}
|
|
166
124
|
|
|
167
125
|
Connection.prototype.password = function (password) {
|
|
168
|
-
|
|
169
|
-
this._send(0x70, this.writer.addCString(password))
|
|
126
|
+
this._send(serialize.password(password))
|
|
170
127
|
}
|
|
171
128
|
|
|
172
129
|
Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) {
|
|
173
|
-
|
|
174
|
-
this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse)
|
|
175
|
-
|
|
176
|
-
this._send(0x70)
|
|
130
|
+
this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse))
|
|
177
131
|
}
|
|
178
132
|
|
|
179
133
|
Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) {
|
|
180
|
-
|
|
181
|
-
this.writer.addString(additionalData)
|
|
182
|
-
|
|
183
|
-
this._send(0x70)
|
|
134
|
+
this._send(serialize.sendSCRAMClientFinalMessage(additionalData))
|
|
184
135
|
}
|
|
185
136
|
|
|
186
|
-
Connection.prototype._send = function (
|
|
137
|
+
Connection.prototype._send = function (buffer) {
|
|
187
138
|
if (!this.stream.writable) {
|
|
188
139
|
return false
|
|
189
140
|
}
|
|
190
|
-
|
|
191
|
-
this.writer.addHeader(code)
|
|
192
|
-
} else {
|
|
193
|
-
return this.stream.write(this.writer.flush(code))
|
|
194
|
-
}
|
|
141
|
+
return this.stream.write(buffer)
|
|
195
142
|
}
|
|
196
143
|
|
|
197
144
|
Connection.prototype.query = function (text) {
|
|
198
|
-
|
|
199
|
-
this.stream.write(this.writer.addCString(text).flush(0x51))
|
|
145
|
+
this._send(serialize.query(text))
|
|
200
146
|
}
|
|
201
147
|
|
|
202
148
|
// send parse message
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// expect something like this:
|
|
206
|
-
// { name: 'queryName',
|
|
207
|
-
// text: 'select * from blah',
|
|
208
|
-
// types: ['int8', 'bool'] }
|
|
209
|
-
|
|
210
|
-
// normalize missing query names to allow for null
|
|
211
|
-
query.name = query.name || ''
|
|
212
|
-
if (query.name.length > 63) {
|
|
213
|
-
/* eslint-disable no-console */
|
|
214
|
-
console.error('Warning! Postgres only supports 63 characters for query names.')
|
|
215
|
-
console.error('You supplied %s (%s)', query.name, query.name.length)
|
|
216
|
-
console.error('This can cause conflicts and silent errors executing queries')
|
|
217
|
-
/* eslint-enable no-console */
|
|
218
|
-
}
|
|
219
|
-
// normalize null type array
|
|
220
|
-
query.types = query.types || []
|
|
221
|
-
var len = query.types.length
|
|
222
|
-
var buffer = this.writer
|
|
223
|
-
.addCString(query.name) // name of query
|
|
224
|
-
.addCString(query.text) // actual query text
|
|
225
|
-
.addInt16(len)
|
|
226
|
-
for (var i = 0; i < len; i++) {
|
|
227
|
-
buffer.addInt32(query.types[i])
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
var code = 0x50
|
|
231
|
-
this._send(code, more)
|
|
149
|
+
Connection.prototype.parse = function (query) {
|
|
150
|
+
this._send(serialize.parse(query))
|
|
232
151
|
}
|
|
233
152
|
|
|
234
153
|
// send bind message
|
|
235
154
|
// "more" === true to buffer the message until flush() is called
|
|
236
|
-
Connection.prototype.bind = function (config
|
|
237
|
-
|
|
238
|
-
config = config || {}
|
|
239
|
-
config.portal = config.portal || ''
|
|
240
|
-
config.statement = config.statement || ''
|
|
241
|
-
config.binary = config.binary || false
|
|
242
|
-
var values = config.values || []
|
|
243
|
-
var len = values.length
|
|
244
|
-
var useBinary = false
|
|
245
|
-
for (var j = 0; j < len; j++) {
|
|
246
|
-
useBinary |= values[j] instanceof Buffer
|
|
247
|
-
}
|
|
248
|
-
var buffer = this.writer.addCString(config.portal).addCString(config.statement)
|
|
249
|
-
if (!useBinary) {
|
|
250
|
-
buffer.addInt16(0)
|
|
251
|
-
} else {
|
|
252
|
-
buffer.addInt16(len)
|
|
253
|
-
for (j = 0; j < len; j++) {
|
|
254
|
-
buffer.addInt16(values[j] instanceof Buffer)
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
buffer.addInt16(len)
|
|
258
|
-
for (var i = 0; i < len; i++) {
|
|
259
|
-
var val = values[i]
|
|
260
|
-
if (val === null || typeof val === 'undefined') {
|
|
261
|
-
buffer.addInt32(-1)
|
|
262
|
-
} else if (val instanceof Buffer) {
|
|
263
|
-
buffer.addInt32(val.length)
|
|
264
|
-
buffer.add(val)
|
|
265
|
-
} else {
|
|
266
|
-
buffer.addInt32(Buffer.byteLength(val))
|
|
267
|
-
buffer.addString(val)
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (config.binary) {
|
|
272
|
-
buffer.addInt16(1) // format codes to use binary
|
|
273
|
-
buffer.addInt16(1)
|
|
274
|
-
} else {
|
|
275
|
-
buffer.addInt16(0) // format codes to use text
|
|
276
|
-
}
|
|
277
|
-
// 0x42 = 'B'
|
|
278
|
-
this._send(0x42, more)
|
|
155
|
+
Connection.prototype.bind = function (config) {
|
|
156
|
+
this._send(serialize.bind(config))
|
|
279
157
|
}
|
|
280
158
|
|
|
281
159
|
// send execute message
|
|
282
160
|
// "more" === true to buffer the message until flush() is called
|
|
283
|
-
Connection.prototype.execute = function (config
|
|
284
|
-
config
|
|
285
|
-
config.portal = config.portal || ''
|
|
286
|
-
config.rows = config.rows || ''
|
|
287
|
-
this.writer.addCString(config.portal).addInt32(config.rows)
|
|
288
|
-
|
|
289
|
-
// 0x45 = 'E'
|
|
290
|
-
this._send(0x45, more)
|
|
161
|
+
Connection.prototype.execute = function (config) {
|
|
162
|
+
this._send(serialize.execute(config))
|
|
291
163
|
}
|
|
292
164
|
|
|
293
|
-
|
|
294
|
-
|
|
165
|
+
const flushBuffer = serialize.flush()
|
|
295
166
|
Connection.prototype.flush = function () {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
167
|
+
if (this.stream.writable) {
|
|
168
|
+
this.stream.write(flushBuffer)
|
|
169
|
+
}
|
|
299
170
|
}
|
|
300
171
|
|
|
172
|
+
const syncBuffer = serialize.sync()
|
|
301
173
|
Connection.prototype.sync = function () {
|
|
302
|
-
// clear out any pending data in the writer
|
|
303
|
-
this.writer.flush(0)
|
|
304
|
-
|
|
305
|
-
this.writer.add(emptyBuffer)
|
|
306
174
|
this._ending = true
|
|
307
|
-
this._send(
|
|
175
|
+
this._send(flushBuffer)
|
|
176
|
+
this._send(syncBuffer)
|
|
308
177
|
}
|
|
309
178
|
|
|
310
|
-
const
|
|
179
|
+
const endBuffer = serialize.end()
|
|
311
180
|
|
|
312
181
|
Connection.prototype.end = function () {
|
|
313
182
|
// 0x58 = 'X'
|
|
314
|
-
this.writer.add(emptyBuffer)
|
|
315
183
|
this._ending = true
|
|
316
184
|
if (!this._connecting || !this.stream.writable) {
|
|
317
185
|
this.stream.end()
|
|
318
186
|
return
|
|
319
187
|
}
|
|
320
|
-
return this.stream.write(
|
|
188
|
+
return this.stream.write(endBuffer, () => {
|
|
321
189
|
this.stream.end()
|
|
322
190
|
})
|
|
323
191
|
}
|
|
324
192
|
|
|
325
|
-
Connection.prototype.close = function (msg
|
|
326
|
-
this.
|
|
327
|
-
this._send(0x43, more)
|
|
193
|
+
Connection.prototype.close = function (msg) {
|
|
194
|
+
this._send(serialize.close(msg))
|
|
328
195
|
}
|
|
329
196
|
|
|
330
|
-
Connection.prototype.describe = function (msg
|
|
331
|
-
this.
|
|
332
|
-
this._send(0x44, more)
|
|
197
|
+
Connection.prototype.describe = function (msg) {
|
|
198
|
+
this._send(serialize.describe(msg))
|
|
333
199
|
}
|
|
334
200
|
|
|
335
201
|
Connection.prototype.sendCopyFromChunk = function (chunk) {
|
|
336
|
-
this.
|
|
202
|
+
this._send(serialize.copyData(chunk))
|
|
337
203
|
}
|
|
338
204
|
|
|
339
205
|
Connection.prototype.endCopyFrom = function () {
|
|
340
|
-
this.
|
|
206
|
+
this._send(serialize.copyDone())
|
|
341
207
|
}
|
|
342
208
|
|
|
343
209
|
Connection.prototype.sendCopyFail = function (msg) {
|
|
344
|
-
|
|
345
|
-
this.writer.addCString(msg)
|
|
346
|
-
this._send(0x66)
|
|
210
|
+
this._send(serialize.copyFail(msg))
|
|
347
211
|
}
|
|
348
212
|
|
|
349
|
-
var Message = function (name, length) {
|
|
350
|
-
this.name = name
|
|
351
|
-
this.length = length
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
Connection.prototype.parseMessage = function (buffer) {
|
|
355
|
-
this.offset = 0
|
|
356
|
-
var length = buffer.length + 4
|
|
357
|
-
switch (this._reader.header) {
|
|
358
|
-
case 0x52: // R
|
|
359
|
-
return this.parseR(buffer, length)
|
|
360
|
-
|
|
361
|
-
case 0x53: // S
|
|
362
|
-
return this.parseS(buffer, length)
|
|
363
|
-
|
|
364
|
-
case 0x4b: // K
|
|
365
|
-
return this.parseK(buffer, length)
|
|
366
|
-
|
|
367
|
-
case 0x43: // C
|
|
368
|
-
return this.parseC(buffer, length)
|
|
369
|
-
|
|
370
|
-
case 0x5a: // Z
|
|
371
|
-
return this.parseZ(buffer, length)
|
|
372
|
-
|
|
373
|
-
case 0x54: // T
|
|
374
|
-
return this.parseT(buffer, length)
|
|
375
|
-
|
|
376
|
-
case 0x44: // D
|
|
377
|
-
return this.parseD(buffer, length)
|
|
378
|
-
|
|
379
|
-
case 0x45: // E
|
|
380
|
-
return this.parseE(buffer, length)
|
|
381
|
-
|
|
382
|
-
case 0x4e: // N
|
|
383
|
-
return this.parseN(buffer, length)
|
|
384
|
-
|
|
385
|
-
case 0x31: // 1
|
|
386
|
-
return new Message('parseComplete', length)
|
|
387
|
-
|
|
388
|
-
case 0x32: // 2
|
|
389
|
-
return new Message('bindComplete', length)
|
|
390
|
-
|
|
391
|
-
case 0x33: // 3
|
|
392
|
-
return new Message('closeComplete', length)
|
|
393
|
-
|
|
394
|
-
case 0x41: // A
|
|
395
|
-
return this.parseA(buffer, length)
|
|
396
|
-
|
|
397
|
-
case 0x6e: // n
|
|
398
|
-
return new Message('noData', length)
|
|
399
|
-
|
|
400
|
-
case 0x49: // I
|
|
401
|
-
return new Message('emptyQuery', length)
|
|
402
|
-
|
|
403
|
-
case 0x73: // s
|
|
404
|
-
return new Message('portalSuspended', length)
|
|
405
|
-
|
|
406
|
-
case 0x47: // G
|
|
407
|
-
return this.parseG(buffer, length)
|
|
408
|
-
|
|
409
|
-
case 0x48: // H
|
|
410
|
-
return this.parseH(buffer, length)
|
|
411
|
-
|
|
412
|
-
case 0x57: // W
|
|
413
|
-
return new Message('replicationStart', length)
|
|
414
|
-
|
|
415
|
-
case 0x63: // c
|
|
416
|
-
return new Message('copyDone', length)
|
|
417
|
-
|
|
418
|
-
case 0x64: // d
|
|
419
|
-
return this.parsed(buffer, length)
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
Connection.prototype.parseR = function (buffer, length) {
|
|
424
|
-
var code = this.parseInt32(buffer)
|
|
425
|
-
|
|
426
|
-
var msg = new Message('authenticationOk', length)
|
|
427
|
-
|
|
428
|
-
switch (code) {
|
|
429
|
-
case 0: // AuthenticationOk
|
|
430
|
-
return msg
|
|
431
|
-
case 3: // AuthenticationCleartextPassword
|
|
432
|
-
if (msg.length === 8) {
|
|
433
|
-
msg.name = 'authenticationCleartextPassword'
|
|
434
|
-
return msg
|
|
435
|
-
}
|
|
436
|
-
break
|
|
437
|
-
case 5: // AuthenticationMD5Password
|
|
438
|
-
if (msg.length === 12) {
|
|
439
|
-
msg.name = 'authenticationMD5Password'
|
|
440
|
-
msg.salt = Buffer.alloc(4)
|
|
441
|
-
buffer.copy(msg.salt, 0, this.offset, this.offset + 4)
|
|
442
|
-
this.offset += 4
|
|
443
|
-
return msg
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
break
|
|
447
|
-
case 10: // AuthenticationSASL
|
|
448
|
-
msg.name = 'authenticationSASL'
|
|
449
|
-
msg.mechanisms = []
|
|
450
|
-
do {
|
|
451
|
-
var mechanism = this.parseCString(buffer)
|
|
452
|
-
|
|
453
|
-
if (mechanism) {
|
|
454
|
-
msg.mechanisms.push(mechanism)
|
|
455
|
-
}
|
|
456
|
-
} while (mechanism)
|
|
457
|
-
|
|
458
|
-
return msg
|
|
459
|
-
case 11: // AuthenticationSASLContinue
|
|
460
|
-
msg.name = 'authenticationSASLContinue'
|
|
461
|
-
msg.data = this.readString(buffer, length - 4)
|
|
462
|
-
|
|
463
|
-
return msg
|
|
464
|
-
case 12: // AuthenticationSASLFinal
|
|
465
|
-
msg.name = 'authenticationSASLFinal'
|
|
466
|
-
msg.data = this.readString(buffer, length - 4)
|
|
467
|
-
|
|
468
|
-
return msg
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
throw new Error('Unknown authenticationOk message type' + util.inspect(msg))
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
Connection.prototype.parseS = function (buffer, length) {
|
|
475
|
-
var msg = new Message('parameterStatus', length)
|
|
476
|
-
msg.parameterName = this.parseCString(buffer)
|
|
477
|
-
msg.parameterValue = this.parseCString(buffer)
|
|
478
|
-
return msg
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
Connection.prototype.parseK = function (buffer, length) {
|
|
482
|
-
var msg = new Message('backendKeyData', length)
|
|
483
|
-
msg.processID = this.parseInt32(buffer)
|
|
484
|
-
msg.secretKey = this.parseInt32(buffer)
|
|
485
|
-
return msg
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
Connection.prototype.parseC = function (buffer, length) {
|
|
489
|
-
var msg = new Message('commandComplete', length)
|
|
490
|
-
msg.text = this.parseCString(buffer)
|
|
491
|
-
return msg
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
Connection.prototype.parseZ = function (buffer, length) {
|
|
495
|
-
var msg = new Message('readyForQuery', length)
|
|
496
|
-
msg.name = 'readyForQuery'
|
|
497
|
-
msg.status = this.readString(buffer, 1)
|
|
498
|
-
return msg
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
var ROW_DESCRIPTION = 'rowDescription'
|
|
502
|
-
Connection.prototype.parseT = function (buffer, length) {
|
|
503
|
-
var msg = new Message(ROW_DESCRIPTION, length)
|
|
504
|
-
msg.fieldCount = this.parseInt16(buffer)
|
|
505
|
-
var fields = []
|
|
506
|
-
for (var i = 0; i < msg.fieldCount; i++) {
|
|
507
|
-
fields.push(this.parseField(buffer))
|
|
508
|
-
}
|
|
509
|
-
msg.fields = fields
|
|
510
|
-
return msg
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
var Field = function () {
|
|
514
|
-
this.name = null
|
|
515
|
-
this.tableID = null
|
|
516
|
-
this.columnID = null
|
|
517
|
-
this.dataTypeID = null
|
|
518
|
-
this.dataTypeSize = null
|
|
519
|
-
this.dataTypeModifier = null
|
|
520
|
-
this.format = null
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
var FORMAT_TEXT = 'text'
|
|
524
|
-
var FORMAT_BINARY = 'binary'
|
|
525
|
-
Connection.prototype.parseField = function (buffer) {
|
|
526
|
-
var field = new Field()
|
|
527
|
-
field.name = this.parseCString(buffer)
|
|
528
|
-
field.tableID = this.parseInt32(buffer)
|
|
529
|
-
field.columnID = this.parseInt16(buffer)
|
|
530
|
-
field.dataTypeID = this.parseInt32(buffer)
|
|
531
|
-
field.dataTypeSize = this.parseInt16(buffer)
|
|
532
|
-
field.dataTypeModifier = this.parseInt32(buffer)
|
|
533
|
-
if (this.parseInt16(buffer) === TEXT_MODE) {
|
|
534
|
-
this._mode = TEXT_MODE
|
|
535
|
-
field.format = FORMAT_TEXT
|
|
536
|
-
} else {
|
|
537
|
-
this._mode = BINARY_MODE
|
|
538
|
-
field.format = FORMAT_BINARY
|
|
539
|
-
}
|
|
540
|
-
return field
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
var DATA_ROW = 'dataRow'
|
|
544
|
-
var DataRowMessage = function (length, fieldCount) {
|
|
545
|
-
this.name = DATA_ROW
|
|
546
|
-
this.length = length
|
|
547
|
-
this.fieldCount = fieldCount
|
|
548
|
-
this.fields = []
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
// extremely hot-path code
|
|
552
|
-
Connection.prototype.parseD = function (buffer, length) {
|
|
553
|
-
var fieldCount = this.parseInt16(buffer)
|
|
554
|
-
var msg = new DataRowMessage(length, fieldCount)
|
|
555
|
-
for (var i = 0; i < fieldCount; i++) {
|
|
556
|
-
msg.fields.push(this._readValue(buffer))
|
|
557
|
-
}
|
|
558
|
-
return msg
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// extremely hot-path code
|
|
562
|
-
Connection.prototype._readValue = function (buffer) {
|
|
563
|
-
var length = this.parseInt32(buffer)
|
|
564
|
-
if (length === -1) return null
|
|
565
|
-
if (this._mode === TEXT_MODE) {
|
|
566
|
-
return this.readString(buffer, length)
|
|
567
|
-
}
|
|
568
|
-
return this.readBytes(buffer, length)
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// parses error
|
|
572
|
-
Connection.prototype.parseE = function (buffer, length, isNotice) {
|
|
573
|
-
var fields = {}
|
|
574
|
-
var fieldType = this.readString(buffer, 1)
|
|
575
|
-
while (fieldType !== '\0') {
|
|
576
|
-
fields[fieldType] = this.parseCString(buffer)
|
|
577
|
-
fieldType = this.readString(buffer, 1)
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// the msg is an Error instance
|
|
581
|
-
var msg = isNotice ? { message: fields.M } : new Error(fields.M)
|
|
582
|
-
|
|
583
|
-
// for compatibility with Message
|
|
584
|
-
msg.name = isNotice ? 'notice' : 'error'
|
|
585
|
-
msg.length = length
|
|
586
|
-
|
|
587
|
-
msg.severity = fields.S
|
|
588
|
-
msg.code = fields.C
|
|
589
|
-
msg.detail = fields.D
|
|
590
|
-
msg.hint = fields.H
|
|
591
|
-
msg.position = fields.P
|
|
592
|
-
msg.internalPosition = fields.p
|
|
593
|
-
msg.internalQuery = fields.q
|
|
594
|
-
msg.where = fields.W
|
|
595
|
-
msg.schema = fields.s
|
|
596
|
-
msg.table = fields.t
|
|
597
|
-
msg.column = fields.c
|
|
598
|
-
msg.dataType = fields.d
|
|
599
|
-
msg.constraint = fields.n
|
|
600
|
-
msg.file = fields.F
|
|
601
|
-
msg.line = fields.L
|
|
602
|
-
msg.routine = fields.R
|
|
603
|
-
return msg
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// same thing, different name
|
|
607
|
-
Connection.prototype.parseN = function (buffer, length) {
|
|
608
|
-
var msg = this.parseE(buffer, length, true)
|
|
609
|
-
msg.name = 'notice'
|
|
610
|
-
return msg
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
Connection.prototype.parseA = function (buffer, length) {
|
|
614
|
-
var msg = new Message('notification', length)
|
|
615
|
-
msg.processId = this.parseInt32(buffer)
|
|
616
|
-
msg.channel = this.parseCString(buffer)
|
|
617
|
-
msg.payload = this.parseCString(buffer)
|
|
618
|
-
return msg
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
Connection.prototype.parseG = function (buffer, length) {
|
|
622
|
-
var msg = new Message('copyInResponse', length)
|
|
623
|
-
return this.parseGH(buffer, msg)
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
Connection.prototype.parseH = function (buffer, length) {
|
|
627
|
-
var msg = new Message('copyOutResponse', length)
|
|
628
|
-
return this.parseGH(buffer, msg)
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
Connection.prototype.parseGH = function (buffer, msg) {
|
|
632
|
-
var isBinary = buffer[this.offset] !== 0
|
|
633
|
-
this.offset++
|
|
634
|
-
msg.binary = isBinary
|
|
635
|
-
var columnCount = this.parseInt16(buffer)
|
|
636
|
-
msg.columnTypes = []
|
|
637
|
-
for (var i = 0; i < columnCount; i++) {
|
|
638
|
-
msg.columnTypes.push(this.parseInt16(buffer))
|
|
639
|
-
}
|
|
640
|
-
return msg
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
Connection.prototype.parsed = function (buffer, length) {
|
|
644
|
-
var msg = new Message('copyData', length)
|
|
645
|
-
msg.chunk = this.readBytes(buffer, msg.length - 4)
|
|
646
|
-
return msg
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
Connection.prototype.parseInt32 = function (buffer) {
|
|
650
|
-
var value = buffer.readInt32BE(this.offset)
|
|
651
|
-
this.offset += 4
|
|
652
|
-
return value
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
Connection.prototype.parseInt16 = function (buffer) {
|
|
656
|
-
var value = buffer.readInt16BE(this.offset)
|
|
657
|
-
this.offset += 2
|
|
658
|
-
return value
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
Connection.prototype.readString = function (buffer, length) {
|
|
662
|
-
return buffer.toString(this.encoding, this.offset, (this.offset += length))
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
Connection.prototype.readBytes = function (buffer, length) {
|
|
666
|
-
return buffer.slice(this.offset, (this.offset += length))
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
Connection.prototype.parseCString = function (buffer) {
|
|
670
|
-
var start = this.offset
|
|
671
|
-
var end = buffer.indexOf(0, start)
|
|
672
|
-
this.offset = end + 1
|
|
673
|
-
return buffer.toString(this.encoding, start, end)
|
|
674
|
-
}
|
|
675
|
-
// end parsing methods
|
|
676
213
|
module.exports = Connection
|
package/lib/defaults.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "PostgreSQL client - pure javascript & libpq with the same API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"buffer-writer": "2.0.0",
|
|
23
23
|
"packet-reader": "1.0.0",
|
|
24
|
-
"pg-connection-string": "^2.
|
|
25
|
-
"pg-pool": "^3.2.
|
|
26
|
-
"pg-protocol": "^1.2.
|
|
24
|
+
"pg-connection-string": "^2.3.0",
|
|
25
|
+
"pg-pool": "^3.2.1",
|
|
26
|
+
"pg-protocol": "^1.2.5",
|
|
27
27
|
"pg-types": "^2.1.0",
|
|
28
28
|
"pgpass": "1.x",
|
|
29
29
|
"semver": "4.3.2"
|
|
@@ -45,6 +45,5 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">= 8.0.0"
|
|
48
|
-
}
|
|
49
|
-
"gitHead": "3f5bc58a86cda3b4812addc1e42a06d61d31e614"
|
|
48
|
+
}
|
|
50
49
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2010 - 2020 Brian Carlson
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/lib/connection-fast.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
/**
|
|
3
|
-
* Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com)
|
|
4
|
-
* All rights reserved.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* README.md file in the root directory of this source tree.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
var net = require('net')
|
|
11
|
-
var EventEmitter = require('events').EventEmitter
|
|
12
|
-
var util = require('util')
|
|
13
|
-
|
|
14
|
-
const { parse, serialize } = require('pg-protocol')
|
|
15
|
-
|
|
16
|
-
// TODO(bmc) support binary mode at some point
|
|
17
|
-
console.log('***using faster connection***')
|
|
18
|
-
var Connection = function (config) {
|
|
19
|
-
EventEmitter.call(this)
|
|
20
|
-
config = config || {}
|
|
21
|
-
this.stream = config.stream || new net.Socket()
|
|
22
|
-
this.stream.setNoDelay(true)
|
|
23
|
-
this._keepAlive = config.keepAlive
|
|
24
|
-
this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis
|
|
25
|
-
this.lastBuffer = false
|
|
26
|
-
this.parsedStatements = {}
|
|
27
|
-
this.ssl = config.ssl || false
|
|
28
|
-
this._ending = false
|
|
29
|
-
this._emitMessage = false
|
|
30
|
-
var self = this
|
|
31
|
-
this.on('newListener', function (eventName) {
|
|
32
|
-
if (eventName === 'message') {
|
|
33
|
-
self._emitMessage = true
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
util.inherits(Connection, EventEmitter)
|
|
39
|
-
|
|
40
|
-
Connection.prototype.connect = function (port, host) {
|
|
41
|
-
var self = this
|
|
42
|
-
|
|
43
|
-
this._connecting = true
|
|
44
|
-
this.stream.connect(port, host)
|
|
45
|
-
|
|
46
|
-
this.stream.once('connect', function () {
|
|
47
|
-
if (self._keepAlive) {
|
|
48
|
-
self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis)
|
|
49
|
-
}
|
|
50
|
-
self.emit('connect')
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const reportStreamError = function (error) {
|
|
54
|
-
// errors about disconnections should be ignored during disconnect
|
|
55
|
-
if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
self.emit('error', error)
|
|
59
|
-
}
|
|
60
|
-
this.stream.on('error', reportStreamError)
|
|
61
|
-
|
|
62
|
-
this.stream.on('close', function () {
|
|
63
|
-
self.emit('end')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
if (!this.ssl) {
|
|
67
|
-
return this.attachListeners(this.stream)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.stream.once('data', function (buffer) {
|
|
71
|
-
var responseCode = buffer.toString('utf8')
|
|
72
|
-
switch (responseCode) {
|
|
73
|
-
case 'S': // Server supports SSL connections, continue with a secure connection
|
|
74
|
-
break
|
|
75
|
-
case 'N': // Server does not support SSL connections
|
|
76
|
-
self.stream.end()
|
|
77
|
-
return self.emit('error', new Error('The server does not support SSL connections'))
|
|
78
|
-
default:
|
|
79
|
-
// Any other response byte, including 'E' (ErrorResponse) indicating a server error
|
|
80
|
-
self.stream.end()
|
|
81
|
-
return self.emit('error', new Error('There was an error establishing an SSL connection'))
|
|
82
|
-
}
|
|
83
|
-
var tls = require('tls')
|
|
84
|
-
const options = Object.assign(
|
|
85
|
-
{
|
|
86
|
-
socket: self.stream,
|
|
87
|
-
},
|
|
88
|
-
self.ssl
|
|
89
|
-
)
|
|
90
|
-
if (net.isIP(host) === 0) {
|
|
91
|
-
options.servername = host
|
|
92
|
-
}
|
|
93
|
-
self.stream = tls.connect(options)
|
|
94
|
-
self.attachListeners(self.stream)
|
|
95
|
-
self.stream.on('error', reportStreamError)
|
|
96
|
-
|
|
97
|
-
self.emit('sslconnect')
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
Connection.prototype.attachListeners = function (stream) {
|
|
102
|
-
stream.on('end', () => {
|
|
103
|
-
this.emit('end')
|
|
104
|
-
})
|
|
105
|
-
parse(stream, (msg) => {
|
|
106
|
-
var eventName = msg.name === 'error' ? 'errorMessage' : msg.name
|
|
107
|
-
if (this._emitMessage) {
|
|
108
|
-
this.emit('message', msg)
|
|
109
|
-
}
|
|
110
|
-
this.emit(eventName, msg)
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
Connection.prototype.requestSsl = function () {
|
|
115
|
-
this.stream.write(serialize.requestSsl())
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
Connection.prototype.startup = function (config) {
|
|
119
|
-
this.stream.write(serialize.startup(config))
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
Connection.prototype.cancel = function (processID, secretKey) {
|
|
123
|
-
this._send(serialize.cancel(processID, secretKey))
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
Connection.prototype.password = function (password) {
|
|
127
|
-
this._send(serialize.password(password))
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) {
|
|
131
|
-
this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse))
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) {
|
|
135
|
-
this._send(serialize.sendSCRAMClientFinalMessage(additionalData))
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
Connection.prototype._send = function (buffer) {
|
|
139
|
-
if (!this.stream.writable) {
|
|
140
|
-
return false
|
|
141
|
-
}
|
|
142
|
-
return this.stream.write(buffer)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
Connection.prototype.query = function (text) {
|
|
146
|
-
this._send(serialize.query(text))
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// send parse message
|
|
150
|
-
Connection.prototype.parse = function (query) {
|
|
151
|
-
this._send(serialize.parse(query))
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// send bind message
|
|
155
|
-
// "more" === true to buffer the message until flush() is called
|
|
156
|
-
Connection.prototype.bind = function (config) {
|
|
157
|
-
this._send(serialize.bind(config))
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// send execute message
|
|
161
|
-
// "more" === true to buffer the message until flush() is called
|
|
162
|
-
Connection.prototype.execute = function (config) {
|
|
163
|
-
this._send(serialize.execute(config))
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const flushBuffer = serialize.flush()
|
|
167
|
-
Connection.prototype.flush = function () {
|
|
168
|
-
if (this.stream.writable) {
|
|
169
|
-
this.stream.write(flushBuffer)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const syncBuffer = serialize.sync()
|
|
174
|
-
Connection.prototype.sync = function () {
|
|
175
|
-
this._ending = true
|
|
176
|
-
this._send(syncBuffer)
|
|
177
|
-
this._send(flushBuffer)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const endBuffer = serialize.end()
|
|
181
|
-
|
|
182
|
-
Connection.prototype.end = function () {
|
|
183
|
-
// 0x58 = 'X'
|
|
184
|
-
this._ending = true
|
|
185
|
-
if (!this._connecting || !this.stream.writable) {
|
|
186
|
-
this.stream.end()
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
return this.stream.write(endBuffer, () => {
|
|
190
|
-
this.stream.end()
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
Connection.prototype.close = function (msg) {
|
|
195
|
-
this._send(serialize.close(msg))
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
Connection.prototype.describe = function (msg) {
|
|
199
|
-
this._send(serialize.describe(msg))
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
Connection.prototype.sendCopyFromChunk = function (chunk) {
|
|
203
|
-
this._send(serialize.copyData(chunk))
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
Connection.prototype.endCopyFrom = function () {
|
|
207
|
-
this._send(serialize.copyDone())
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
Connection.prototype.sendCopyFail = function (msg) {
|
|
211
|
-
this._send(serialize.copyFail(msg))
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
module.exports = Connection
|