pg 8.9.0 → 8.11.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/lib/client.js +30 -39
- package/lib/connection.js +5 -7
- package/lib/{sasl.js → crypto/sasl.js} +11 -26
- package/lib/crypto/utils-legacy.js +37 -0
- package/lib/crypto/utils.js +92 -0
- package/lib/index.js +3 -0
- package/lib/native/client.js +7 -1
- package/lib/stream.js +28 -0
- package/lib/utils.js +28 -11
- package/package.json +12 -5
package/lib/client.js
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var EventEmitter = require('events').EventEmitter
|
|
4
4
|
var utils = require('./utils')
|
|
5
|
-
var sasl = require('./sasl')
|
|
6
|
-
var pgPass = require('pgpass')
|
|
5
|
+
var sasl = require('./crypto/sasl')
|
|
7
6
|
var TypeOverrides = require('./type-overrides')
|
|
8
7
|
|
|
9
8
|
var ConnectionParameters = require('./connection-parameters')
|
|
10
9
|
var Query = require('./query')
|
|
11
10
|
var defaults = require('./defaults')
|
|
12
11
|
var Connection = require('./connection')
|
|
12
|
+
const crypto = require('./crypto/utils')
|
|
13
13
|
|
|
14
14
|
class Client extends EventEmitter {
|
|
15
15
|
constructor(config) {
|
|
@@ -37,6 +37,7 @@ class Client extends EventEmitter {
|
|
|
37
37
|
this._Promise = c.Promise || global.Promise
|
|
38
38
|
this._types = new TypeOverrides(c.types)
|
|
39
39
|
this._ending = false
|
|
40
|
+
this._ended = false
|
|
40
41
|
this._connecting = false
|
|
41
42
|
this._connected = false
|
|
42
43
|
this._connectionError = false
|
|
@@ -132,6 +133,7 @@ class Client extends EventEmitter {
|
|
|
132
133
|
|
|
133
134
|
clearTimeout(this.connectionTimeoutHandle)
|
|
134
135
|
this._errorAllQueries(error)
|
|
136
|
+
this._ended = true
|
|
135
137
|
|
|
136
138
|
if (!this._ending) {
|
|
137
139
|
// if the connection is ended without us calling .end()
|
|
@@ -223,12 +225,17 @@ class Client extends EventEmitter {
|
|
|
223
225
|
} else if (this.password !== null) {
|
|
224
226
|
cb()
|
|
225
227
|
} else {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
try {
|
|
229
|
+
const pgPass = require('pgpass')
|
|
230
|
+
pgPass(this.connectionParameters, (pass) => {
|
|
231
|
+
if (undefined !== pass) {
|
|
232
|
+
this.connectionParameters.password = this.password = pass
|
|
233
|
+
}
|
|
234
|
+
cb()
|
|
235
|
+
})
|
|
236
|
+
} catch (e) {
|
|
237
|
+
this.emit('error', e)
|
|
238
|
+
}
|
|
232
239
|
}
|
|
233
240
|
}
|
|
234
241
|
|
|
@@ -239,9 +246,13 @@ class Client extends EventEmitter {
|
|
|
239
246
|
}
|
|
240
247
|
|
|
241
248
|
_handleAuthMD5Password(msg) {
|
|
242
|
-
this._checkPgPass(() => {
|
|
243
|
-
|
|
244
|
-
|
|
249
|
+
this._checkPgPass(async () => {
|
|
250
|
+
try {
|
|
251
|
+
const hashedPassword = await crypto.postgresMd5PasswordHash(this.user, this.password, msg.salt)
|
|
252
|
+
this.connection.password(hashedPassword)
|
|
253
|
+
} catch (e) {
|
|
254
|
+
this.emit('error', e)
|
|
255
|
+
}
|
|
245
256
|
})
|
|
246
257
|
}
|
|
247
258
|
|
|
@@ -256,9 +267,9 @@ class Client extends EventEmitter {
|
|
|
256
267
|
})
|
|
257
268
|
}
|
|
258
269
|
|
|
259
|
-
_handleAuthSASLContinue(msg) {
|
|
270
|
+
async _handleAuthSASLContinue(msg) {
|
|
260
271
|
try {
|
|
261
|
-
sasl.continueSession(this.saslSession, this.password, msg.data)
|
|
272
|
+
await sasl.continueSession(this.saslSession, this.password, msg.data)
|
|
262
273
|
this.connection.sendSCRAMClientFinalMessage(this.saslSession.response)
|
|
263
274
|
} catch (err) {
|
|
264
275
|
this.connection.emit('error', err)
|
|
@@ -454,35 +465,15 @@ class Client extends EventEmitter {
|
|
|
454
465
|
return this._types.getTypeParser(oid, format)
|
|
455
466
|
}
|
|
456
467
|
|
|
457
|
-
//
|
|
468
|
+
// escapeIdentifier and escapeLiteral moved to utility functions & exported
|
|
469
|
+
// on PG
|
|
470
|
+
// re-exported here for backwards compatibility
|
|
458
471
|
escapeIdentifier(str) {
|
|
459
|
-
return
|
|
472
|
+
return utils.escapeIdentifier(str)
|
|
460
473
|
}
|
|
461
474
|
|
|
462
|
-
// Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c
|
|
463
475
|
escapeLiteral(str) {
|
|
464
|
-
|
|
465
|
-
var escaped = "'"
|
|
466
|
-
|
|
467
|
-
for (var i = 0; i < str.length; i++) {
|
|
468
|
-
var c = str[i]
|
|
469
|
-
if (c === "'") {
|
|
470
|
-
escaped += c + c
|
|
471
|
-
} else if (c === '\\') {
|
|
472
|
-
escaped += c + c
|
|
473
|
-
hasBackslash = true
|
|
474
|
-
} else {
|
|
475
|
-
escaped += c
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
escaped += "'"
|
|
480
|
-
|
|
481
|
-
if (hasBackslash === true) {
|
|
482
|
-
escaped = ' E' + escaped
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
return escaped
|
|
476
|
+
return utils.escapeLiteral(str)
|
|
486
477
|
}
|
|
487
478
|
|
|
488
479
|
_pulseQueryQueue() {
|
|
@@ -603,7 +594,7 @@ class Client extends EventEmitter {
|
|
|
603
594
|
this._ending = true
|
|
604
595
|
|
|
605
596
|
// if we have never connected, then end is a noop, callback immediately
|
|
606
|
-
if (!this.connection._connecting) {
|
|
597
|
+
if (!this.connection._connecting || this._ended) {
|
|
607
598
|
if (cb) {
|
|
608
599
|
cb()
|
|
609
600
|
} else {
|
package/lib/connection.js
CHANGED
|
@@ -4,6 +4,7 @@ var net = require('net')
|
|
|
4
4
|
var EventEmitter = require('events').EventEmitter
|
|
5
5
|
|
|
6
6
|
const { parse, serialize } = require('pg-protocol')
|
|
7
|
+
const { getStream, getSecureStream } = require('./stream')
|
|
7
8
|
|
|
8
9
|
const flushBuffer = serialize.flush()
|
|
9
10
|
const syncBuffer = serialize.sync()
|
|
@@ -15,7 +16,7 @@ class Connection extends EventEmitter {
|
|
|
15
16
|
super()
|
|
16
17
|
config = config || {}
|
|
17
18
|
|
|
18
|
-
this.stream = config.stream ||
|
|
19
|
+
this.stream = config.stream || getStream(config.ssl)
|
|
19
20
|
if (typeof this.stream === 'function') {
|
|
20
21
|
this.stream = this.stream(config)
|
|
21
22
|
}
|
|
@@ -79,7 +80,6 @@ class Connection extends EventEmitter {
|
|
|
79
80
|
self.stream.end()
|
|
80
81
|
return self.emit('error', new Error('There was an error establishing an SSL connection'))
|
|
81
82
|
}
|
|
82
|
-
var tls = require('tls')
|
|
83
83
|
const options = {
|
|
84
84
|
socket: self.stream,
|
|
85
85
|
}
|
|
@@ -92,11 +92,12 @@ class Connection extends EventEmitter {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
var net = require('net')
|
|
96
|
+
if (net.isIP && net.isIP(host) === 0) {
|
|
96
97
|
options.servername = host
|
|
97
98
|
}
|
|
98
99
|
try {
|
|
99
|
-
self.stream =
|
|
100
|
+
self.stream = getSecureStream(options)
|
|
100
101
|
} catch (err) {
|
|
101
102
|
return self.emit('error', err)
|
|
102
103
|
}
|
|
@@ -108,9 +109,6 @@ class Connection extends EventEmitter {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
attachListeners(stream) {
|
|
111
|
-
stream.on('end', () => {
|
|
112
|
-
this.emit('end')
|
|
113
|
-
})
|
|
114
112
|
parse(stream, (msg) => {
|
|
115
113
|
var eventName = msg.name === 'error' ? 'errorMessage' : msg.name
|
|
116
114
|
if (this._emitMessage) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const crypto = require('
|
|
2
|
+
const crypto = require('./utils')
|
|
3
3
|
|
|
4
4
|
function startSession(mechanisms) {
|
|
5
5
|
if (mechanisms.indexOf('SCRAM-SHA-256') === -1) {
|
|
@@ -16,7 +16,7 @@ function startSession(mechanisms) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function continueSession(session, password, serverData) {
|
|
19
|
+
async function continueSession(session, password, serverData) {
|
|
20
20
|
if (session.message !== 'SASLInitialResponse') {
|
|
21
21
|
throw new Error('SASL: Last message was not SASLInitialResponse')
|
|
22
22
|
}
|
|
@@ -38,29 +38,22 @@ function continueSession(session, password, serverData) {
|
|
|
38
38
|
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short')
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
var saltBytes = Buffer.from(sv.salt, 'base64')
|
|
42
|
-
|
|
43
|
-
var saltedPassword = crypto.pbkdf2Sync(password, saltBytes, sv.iteration, 32, 'sha256')
|
|
44
|
-
|
|
45
|
-
var clientKey = hmacSha256(saltedPassword, 'Client Key')
|
|
46
|
-
var storedKey = sha256(clientKey)
|
|
47
|
-
|
|
48
41
|
var clientFirstMessageBare = 'n=*,r=' + session.clientNonce
|
|
49
42
|
var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration
|
|
50
|
-
|
|
51
43
|
var clientFinalMessageWithoutProof = 'c=biws,r=' + sv.nonce
|
|
52
|
-
|
|
53
44
|
var authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof
|
|
54
45
|
|
|
55
|
-
var
|
|
56
|
-
var
|
|
57
|
-
var
|
|
58
|
-
|
|
59
|
-
var
|
|
60
|
-
var
|
|
46
|
+
var saltBytes = Buffer.from(sv.salt, 'base64')
|
|
47
|
+
var saltedPassword = await crypto.deriveKey(password, saltBytes, sv.iteration)
|
|
48
|
+
var clientKey = await crypto.hmacSha256(saltedPassword, 'Client Key')
|
|
49
|
+
var storedKey = await crypto.sha256(clientKey)
|
|
50
|
+
var clientSignature = await crypto.hmacSha256(storedKey, authMessage)
|
|
51
|
+
var clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString('base64')
|
|
52
|
+
var serverKey = await crypto.hmacSha256(saltedPassword, 'Server Key')
|
|
53
|
+
var serverSignatureBytes = await crypto.hmacSha256(serverKey, authMessage)
|
|
61
54
|
|
|
62
55
|
session.message = 'SASLResponse'
|
|
63
|
-
session.serverSignature = serverSignatureBytes.toString('base64')
|
|
56
|
+
session.serverSignature = Buffer.from(serverSignatureBytes).toString('base64')
|
|
64
57
|
session.response = clientFinalMessageWithoutProof + ',p=' + clientProof
|
|
65
58
|
}
|
|
66
59
|
|
|
@@ -186,14 +179,6 @@ function xorBuffers(a, b) {
|
|
|
186
179
|
return Buffer.from(a.map((_, i) => a[i] ^ b[i]))
|
|
187
180
|
}
|
|
188
181
|
|
|
189
|
-
function sha256(text) {
|
|
190
|
-
return crypto.createHash('sha256').update(text).digest()
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function hmacSha256(key, msg) {
|
|
194
|
-
return crypto.createHmac('sha256', key).update(msg).digest()
|
|
195
|
-
}
|
|
196
|
-
|
|
197
182
|
module.exports = {
|
|
198
183
|
startSession,
|
|
199
184
|
continueSession,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
// This file contains crypto utility functions for versions of Node.js < 15.0.0,
|
|
3
|
+
// which does not support the WebCrypto.subtle API.
|
|
4
|
+
|
|
5
|
+
const nodeCrypto = require('crypto')
|
|
6
|
+
|
|
7
|
+
function md5(string) {
|
|
8
|
+
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
|
|
12
|
+
function postgresMd5PasswordHash(user, password, salt) {
|
|
13
|
+
var inner = md5(password + user)
|
|
14
|
+
var outer = md5(Buffer.concat([Buffer.from(inner), salt]))
|
|
15
|
+
return 'md5' + outer
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function sha256(text) {
|
|
19
|
+
return nodeCrypto.createHash('sha256').update(text).digest()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function hmacSha256(key, msg) {
|
|
23
|
+
return nodeCrypto.createHmac('sha256', key).update(msg).digest()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function deriveKey(password, salt, iterations) {
|
|
27
|
+
return nodeCrypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
postgresMd5PasswordHash,
|
|
32
|
+
randomBytes: nodeCrypto.randomBytes,
|
|
33
|
+
deriveKey,
|
|
34
|
+
sha256,
|
|
35
|
+
hmacSha256,
|
|
36
|
+
md5,
|
|
37
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const useLegacyCrypto = parseInt(process.versions && process.versions.node && process.versions.node.split('.')[0]) < 15
|
|
4
|
+
if (useLegacyCrypto) {
|
|
5
|
+
// We are on an old version of Node.js that requires legacy crypto utilities.
|
|
6
|
+
module.exports = require('./utils-legacy')
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const nodeCrypto = require('crypto')
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
postgresMd5PasswordHash,
|
|
14
|
+
randomBytes,
|
|
15
|
+
deriveKey,
|
|
16
|
+
sha256,
|
|
17
|
+
hmacSha256,
|
|
18
|
+
md5,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The Web Crypto API - grabbed from the Node.js library or the global
|
|
23
|
+
* @type Crypto
|
|
24
|
+
*/
|
|
25
|
+
const webCrypto = nodeCrypto.webcrypto || globalThis.crypto
|
|
26
|
+
/**
|
|
27
|
+
* The SubtleCrypto API for low level crypto operations.
|
|
28
|
+
* @type SubtleCrypto
|
|
29
|
+
*/
|
|
30
|
+
const subtleCrypto = webCrypto.subtle
|
|
31
|
+
const textEncoder = new TextEncoder()
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param {*} length
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
function randomBytes(length) {
|
|
39
|
+
return webCrypto.getRandomValues(Buffer.alloc(length))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function md5(string) {
|
|
43
|
+
try {
|
|
44
|
+
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
|
|
45
|
+
} catch (e) {
|
|
46
|
+
// `createHash()` failed so we are probably not in Node.js, use the WebCrypto API instead.
|
|
47
|
+
// Note that the MD5 algorithm on WebCrypto is not available in Node.js.
|
|
48
|
+
// This is why we cannot just use WebCrypto in all environments.
|
|
49
|
+
const data = typeof string === 'string' ? textEncoder.encode(string) : string
|
|
50
|
+
const hash = await subtleCrypto.digest('MD5', data)
|
|
51
|
+
return Array.from(new Uint8Array(hash))
|
|
52
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
53
|
+
.join('')
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
|
|
58
|
+
async function postgresMd5PasswordHash(user, password, salt) {
|
|
59
|
+
var inner = await md5(password + user)
|
|
60
|
+
var outer = await md5(Buffer.concat([Buffer.from(inner), salt]))
|
|
61
|
+
return 'md5' + outer
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a SHA-256 digest of the given data
|
|
66
|
+
* @param {Buffer} data
|
|
67
|
+
*/
|
|
68
|
+
async function sha256(text) {
|
|
69
|
+
return await subtleCrypto.digest('SHA-256', text)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sign the message with the given key
|
|
74
|
+
* @param {ArrayBuffer} keyBuffer
|
|
75
|
+
* @param {string} msg
|
|
76
|
+
*/
|
|
77
|
+
async function hmacSha256(keyBuffer, msg) {
|
|
78
|
+
const key = await subtleCrypto.importKey('raw', keyBuffer, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
|
|
79
|
+
return await subtleCrypto.sign('HMAC', key, textEncoder.encode(msg))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Derive a key from the password and salt
|
|
84
|
+
* @param {string} password
|
|
85
|
+
* @param {Uint8Array} salt
|
|
86
|
+
* @param {number} iterations
|
|
87
|
+
*/
|
|
88
|
+
async function deriveKey(password, salt, iterations) {
|
|
89
|
+
const key = await subtleCrypto.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits'])
|
|
90
|
+
const params = { name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations: iterations }
|
|
91
|
+
return await subtleCrypto.deriveBits(params, key, 32 * 8, ['deriveBits'])
|
|
92
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -5,6 +5,7 @@ var defaults = require('./defaults')
|
|
|
5
5
|
var Connection = require('./connection')
|
|
6
6
|
var Pool = require('pg-pool')
|
|
7
7
|
const { DatabaseError } = require('pg-protocol')
|
|
8
|
+
const { escapeIdentifier, escapeLiteral } = require('./utils')
|
|
8
9
|
|
|
9
10
|
const poolFactory = (Client) => {
|
|
10
11
|
return class BoundPool extends Pool {
|
|
@@ -23,6 +24,8 @@ var PG = function (clientConstructor) {
|
|
|
23
24
|
this.Connection = Connection
|
|
24
25
|
this.types = require('pg-types')
|
|
25
26
|
this.DatabaseError = DatabaseError
|
|
27
|
+
this.escapeIdentifier = escapeIdentifier
|
|
28
|
+
this.escapeLiteral = escapeLiteral
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') {
|
package/lib/native/client.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line
|
|
4
|
-
var Native
|
|
4
|
+
var Native
|
|
5
|
+
try {
|
|
6
|
+
// Wrap this `require()` in a try-catch to avoid upstream bundlers from complaining that this might not be available since it is an optional import
|
|
7
|
+
Native = require('pg-native')
|
|
8
|
+
} catch (e) {
|
|
9
|
+
throw e
|
|
10
|
+
}
|
|
5
11
|
var TypeOverrides = require('../type-overrides')
|
|
6
12
|
var EventEmitter = require('events').EventEmitter
|
|
7
13
|
var util = require('util')
|
package/lib/stream.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get a socket stream compatible with the current runtime environment.
|
|
3
|
+
* @returns {Duplex}
|
|
4
|
+
*/
|
|
5
|
+
module.exports.getStream = function getStream(ssl) {
|
|
6
|
+
const net = require('net')
|
|
7
|
+
if (typeof net.Socket === 'function') {
|
|
8
|
+
return new net.Socket()
|
|
9
|
+
} else {
|
|
10
|
+
const { CloudflareSocket } = require('pg-cloudflare')
|
|
11
|
+
return new CloudflareSocket(ssl)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get a TLS secured socket, compatible with the current environment,
|
|
17
|
+
* using the socket and other settings given in `options`.
|
|
18
|
+
* @returns {Duplex}
|
|
19
|
+
*/
|
|
20
|
+
module.exports.getSecureStream = function getSecureStream(options) {
|
|
21
|
+
var tls = require('tls')
|
|
22
|
+
if (tls.connect) {
|
|
23
|
+
return tls.connect(options)
|
|
24
|
+
} else {
|
|
25
|
+
options.socket.startTls(options)
|
|
26
|
+
return options.socket
|
|
27
|
+
}
|
|
28
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const crypto = require('crypto')
|
|
4
|
-
|
|
5
3
|
const defaults = require('./defaults')
|
|
6
4
|
|
|
7
5
|
function escapeElement(elementRepresentation) {
|
|
@@ -164,15 +162,34 @@ function normalizeQueryConfig(config, values, callback) {
|
|
|
164
162
|
return config
|
|
165
163
|
}
|
|
166
164
|
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
// Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c
|
|
166
|
+
const escapeIdentifier = function (str) {
|
|
167
|
+
return '"' + str.replace(/"/g, '""') + '"'
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
var
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
const escapeLiteral = function (str) {
|
|
171
|
+
var hasBackslash = false
|
|
172
|
+
var escaped = "'"
|
|
173
|
+
|
|
174
|
+
for (var i = 0; i < str.length; i++) {
|
|
175
|
+
var c = str[i]
|
|
176
|
+
if (c === "'") {
|
|
177
|
+
escaped += c + c
|
|
178
|
+
} else if (c === '\\') {
|
|
179
|
+
escaped += c + c
|
|
180
|
+
hasBackslash = true
|
|
181
|
+
} else {
|
|
182
|
+
escaped += c
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
escaped += "'"
|
|
187
|
+
|
|
188
|
+
if (hasBackslash === true) {
|
|
189
|
+
escaped = ' E' + escaped
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return escaped
|
|
176
193
|
}
|
|
177
194
|
|
|
178
195
|
module.exports = {
|
|
@@ -182,6 +199,6 @@ module.exports = {
|
|
|
182
199
|
return prepareValue(value)
|
|
183
200
|
},
|
|
184
201
|
normalizeQueryConfig,
|
|
185
|
-
|
|
186
|
-
|
|
202
|
+
escapeIdentifier,
|
|
203
|
+
escapeLiteral,
|
|
187
204
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.11.0",
|
|
4
4
|
"description": "PostgreSQL client - pure javascript & libpq with the same API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -22,17 +22,24 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"buffer-writer": "2.0.0",
|
|
24
24
|
"packet-reader": "1.0.0",
|
|
25
|
-
"pg-connection-string": "^2.
|
|
26
|
-
"pg-pool": "^3.
|
|
25
|
+
"pg-connection-string": "^2.6.0",
|
|
26
|
+
"pg-pool": "^3.6.0",
|
|
27
27
|
"pg-protocol": "^1.6.0",
|
|
28
28
|
"pg-types": "^2.1.0",
|
|
29
29
|
"pgpass": "1.x"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
+
"@cloudflare/workers-types": "^4.20230404.0",
|
|
32
33
|
"async": "2.6.4",
|
|
33
34
|
"bluebird": "3.5.2",
|
|
34
35
|
"co": "4.6.0",
|
|
35
|
-
"pg-copy-streams": "0.3.0"
|
|
36
|
+
"pg-copy-streams": "0.3.0",
|
|
37
|
+
"typescript": "^4.0.3",
|
|
38
|
+
"workerd": "^1.20230419.0",
|
|
39
|
+
"wrangler": "^2.16.0"
|
|
40
|
+
},
|
|
41
|
+
"optionalDependencies": {
|
|
42
|
+
"pg-cloudflare": "^1.1.0"
|
|
36
43
|
},
|
|
37
44
|
"peerDependencies": {
|
|
38
45
|
"pg-native": ">=3.0.1"
|
|
@@ -53,5 +60,5 @@
|
|
|
53
60
|
"engines": {
|
|
54
61
|
"node": ">= 8.0.0"
|
|
55
62
|
},
|
|
56
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "14b840e96e57fc0617b5c4758f6318f774148ee4"
|
|
57
64
|
}
|