pg 7.8.1 → 7.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/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ For richer information consult the commit log on github with referenced pull req
4
4
 
5
5
  We do not include break-fix version release in this file.
6
6
 
7
+ ### 7.11.0
8
+ - Add support for [connection_timeout](https://github.com/brianc/node-postgres/pull/1847/files#diff-5391bde944956870128be1136e7bc176R63) and [keepalives_idle](https://github.com/brianc/node-postgres/pull/1847).
9
+
10
+ ### 7.10.0
11
+ - Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825).
12
+
13
+ ### 7.9.0
14
+
15
+ - Add support for [sasl/scram authentication](https://github.com/brianc/node-postgres/pull/1835).
16
+
7
17
  ### 7.8.0
8
18
 
9
19
  - Add support for passing [secureOptions](https://github.com/brianc/node-postgres/pull/1804) SSL config.
package/README.md CHANGED
@@ -67,7 +67,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask
67
67
 
68
68
  ## License
69
69
 
70
- Copyright (c) 2010-2018 Brian Carlson (brian.m.carlson@gmail.com)
70
+ Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com)
71
71
 
72
72
  Permission is hereby granted, free of charge, to any person obtaining a copy
73
73
  of this software and associated documentation files (the "Software"), to deal
package/SPONSORS.md CHANGED
@@ -2,6 +2,7 @@ node-postgres is made possible by the helpful contributors from the community we
2
2
 
3
3
  # Leaders
4
4
  - [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu)
5
+ - [Third Iron](https://thirdiron.com/)
5
6
 
6
7
  # Supporters
7
8
  - John Fawcett
package/lib/client.js CHANGED
@@ -10,6 +10,7 @@
10
10
  var EventEmitter = require('events').EventEmitter
11
11
  var util = require('util')
12
12
  var utils = require('./utils')
13
+ var sasl = require('./sasl')
13
14
  var pgPass = require('pgpass')
14
15
  var TypeOverrides = require('./type-overrides')
15
16
 
@@ -43,6 +44,7 @@ var Client = function (config) {
43
44
  stream: c.stream,
44
45
  ssl: this.connectionParameters.ssl,
45
46
  keepAlive: c.keepAlive || false,
47
+ keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0,
46
48
  encoding: this.connectionParameters.client_encoding || 'utf8'
47
49
  })
48
50
  this.queryQueue = []
@@ -50,6 +52,7 @@ var Client = function (config) {
50
52
  this.processID = null
51
53
  this.secretKey = null
52
54
  this.ssl = this.connectionParameters.ssl || false
55
+ this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0
53
56
  }
54
57
 
55
58
  util.inherits(Client, EventEmitter)
@@ -82,6 +85,14 @@ Client.prototype._connect = function (callback) {
82
85
  }
83
86
  this._connecting = true
84
87
 
88
+ var connectionTimeoutHandle
89
+ if (this._connectionTimeoutMillis > 0) {
90
+ connectionTimeoutHandle = setTimeout(() => {
91
+ con._ending = true
92
+ con.stream.destroy(new Error('timeout expired'))
93
+ }, this._connectionTimeoutMillis)
94
+ }
95
+
85
96
  if (this.host && this.host.indexOf('/') === 0) {
86
97
  con.connect(this.host + '/.s.PGSQL.' + this.port)
87
98
  } else {
@@ -126,6 +137,28 @@ Client.prototype._connect = function (callback) {
126
137
  con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt))
127
138
  }))
128
139
 
140
+ // password request handling (SASL)
141
+ var saslSession
142
+ con.on('authenticationSASL', checkPgPass(function (msg) {
143
+ saslSession = sasl.startSession(msg.mechanisms)
144
+
145
+ con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response)
146
+ }))
147
+
148
+ // password request handling (SASL)
149
+ con.on('authenticationSASLContinue', function (msg) {
150
+ sasl.continueSession(saslSession, self.password, msg.data)
151
+
152
+ con.sendSCRAMClientFinalMessage(saslSession.response)
153
+ })
154
+
155
+ // password request handling (SASL)
156
+ con.on('authenticationSASLFinal', function (msg) {
157
+ sasl.finalizeSession(saslSession, msg.data)
158
+
159
+ saslSession = null
160
+ })
161
+
129
162
  con.once('backendKeyData', function (msg) {
130
163
  self.processID = msg.processID
131
164
  self.secretKey = msg.secretKey
@@ -136,6 +169,7 @@ Client.prototype._connect = function (callback) {
136
169
  return
137
170
  }
138
171
  this._connectionError = true
172
+ clearTimeout(connectionTimeoutHandle)
139
173
  if (callback) {
140
174
  return callback(err)
141
175
  }
@@ -173,6 +207,7 @@ Client.prototype._connect = function (callback) {
173
207
  con.removeListener('errorMessage', connectingErrorHandler)
174
208
  con.on('error', connectedErrorHandler)
175
209
  con.on('errorMessage', connectedErrorMessageHandler)
210
+ clearTimeout(connectionTimeoutHandle)
176
211
 
177
212
  // process possible callback argument to Client#connect
178
213
  if (callback) {
@@ -276,7 +311,7 @@ Client.prototype._attachListeners = function (con) {
276
311
  // it again on the same client
277
312
  con.on('parseComplete', function (msg) {
278
313
  if (self.activeQuery.name) {
279
- con.parsedStatements[self.activeQuery.name] = true
314
+ con.parsedStatements[self.activeQuery.name] = self.activeQuery.text
280
315
  }
281
316
  })
282
317
 
@@ -455,8 +490,9 @@ Client.prototype.query = function (config, values, callback) {
455
490
  if (this.binary && !query.binary) {
456
491
  query.binary = true
457
492
  }
458
- if (query._result) {
459
- query._result._getTypeParser = this._types.getTypeParser.bind(this._types)
493
+
494
+ if (query._result && !query._result._types) {
495
+ query._result._types = this._types
460
496
  }
461
497
 
462
498
  if (!this._queryable) {
@@ -66,6 +66,22 @@ var ConnectionParameters = function (config) {
66
66
  this.fallback_application_name = val('fallback_application_name', config, false)
67
67
  this.statement_timeout = val('statement_timeout', config, false)
68
68
  this.query_timeout = val('query_timeout', config, false)
69
+
70
+ if (config.connectionTimeoutMillis === undefined) {
71
+ this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0
72
+ } else {
73
+ this.connect_timeout = Math.floor(config.connectionTimeoutMillis / 1000)
74
+ }
75
+
76
+ if (config.keepAlive === false) {
77
+ this.keepalives = 0
78
+ } else if (config.keepAlive === true) {
79
+ this.keepalives = 1
80
+ }
81
+
82
+ if (typeof config.keepAliveInitialDelayMillis === 'number') {
83
+ this.keepalives_idle = Math.floor(config.keepAliveInitialDelayMillis / 1000)
84
+ }
69
85
  }
70
86
 
71
87
  // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes
@@ -75,7 +91,7 @@ var quoteParamValue = function (value) {
75
91
 
76
92
  var add = function (params, config, paramName) {
77
93
  var value = config[paramName]
78
- if (value) {
94
+ if (value !== undefined && value !== null) {
79
95
  params.push(paramName + '=' + quoteParamValue(value))
80
96
  }
81
97
  }
@@ -87,8 +103,9 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) {
87
103
  add(params, this, 'port')
88
104
  add(params, this, 'application_name')
89
105
  add(params, this, 'fallback_application_name')
106
+ add(params, this, 'connect_timeout')
90
107
 
91
- var ssl = typeof this.ssl === 'object' ? this.ssl : { sslmode: this.ssl }
108
+ var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {}
92
109
  add(params, ssl, 'sslmode')
93
110
  add(params, ssl, 'sslca')
94
111
  add(params, ssl, 'sslkey')
package/lib/connection.js CHANGED
@@ -21,6 +21,7 @@ var Connection = function (config) {
21
21
  config = config || {}
22
22
  this.stream = config.stream || new net.Socket()
23
23
  this._keepAlive = config.keepAlive
24
+ this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis
24
25
  this.lastBuffer = false
25
26
  this.lastOffset = 0
26
27
  this.buffer = null
@@ -47,17 +48,17 @@ var Connection = function (config) {
47
48
  util.inherits(Connection, EventEmitter)
48
49
 
49
50
  Connection.prototype.connect = function (port, host) {
51
+ var self = this
52
+
50
53
  if (this.stream.readyState === 'closed') {
51
54
  this.stream.connect(port, host)
52
55
  } else if (this.stream.readyState === 'open') {
53
56
  this.emit('connect')
54
57
  }
55
58
 
56
- var self = this
57
-
58
59
  this.stream.on('connect', function () {
59
60
  if (self._keepAlive) {
60
- self.stream.setKeepAlive(true)
61
+ self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis)
61
62
  }
62
63
  self.emit('connect')
63
64
  })
@@ -191,6 +192,24 @@ Connection.prototype.password = function (password) {
191
192
  this._send(0x70, this.writer.addCString(password))
192
193
  }
193
194
 
195
+ Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) {
196
+ // 0x70 = 'p'
197
+ this.writer
198
+ .addCString(mechanism)
199
+ .addInt32(Buffer.byteLength(initialResponse))
200
+ .addString(initialResponse)
201
+
202
+ this._send(0x70)
203
+ }
204
+
205
+ Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) {
206
+ // 0x70 = 'p'
207
+ this.writer
208
+ .addString(additionalData)
209
+
210
+ this._send(0x70)
211
+ }
212
+
194
213
  Connection.prototype._send = function (code, more) {
195
214
  if (!this.stream.writable) {
196
215
  return false
@@ -421,25 +440,53 @@ Connection.prototype.parseMessage = function (buffer) {
421
440
  }
422
441
 
423
442
  Connection.prototype.parseR = function (buffer, length) {
424
- var code = 0
443
+ var code = this.parseInt32(buffer)
444
+
425
445
  var msg = new Message('authenticationOk', length)
426
- if (msg.length === 8) {
427
- code = this.parseInt32(buffer)
428
- if (code === 3) {
429
- msg.name = 'authenticationCleartextPassword'
430
- }
431
- return msg
432
- }
433
- if (msg.length === 12) {
434
- code = this.parseInt32(buffer)
435
- if (code === 5) { // md5 required
436
- msg.name = 'authenticationMD5Password'
437
- msg.salt = Buffer.alloc(4)
438
- buffer.copy(msg.salt, 0, this.offset, this.offset + 4)
439
- this.offset += 4
446
+
447
+ switch (code) {
448
+ case 0: // AuthenticationOk
449
+ return msg
450
+ case 3: // AuthenticationCleartextPassword
451
+ if (msg.length === 8) {
452
+ msg.name = 'authenticationCleartextPassword'
453
+ return msg
454
+ }
455
+ break
456
+ case 5: // AuthenticationMD5Password
457
+ if (msg.length === 12) {
458
+ msg.name = 'authenticationMD5Password'
459
+ msg.salt = Buffer.alloc(4)
460
+ buffer.copy(msg.salt, 0, this.offset, this.offset + 4)
461
+ this.offset += 4
462
+ return msg
463
+ }
464
+
465
+ break
466
+ case 10: // AuthenticationSASL
467
+ msg.name = 'authenticationSASL'
468
+ msg.mechanisms = []
469
+ do {
470
+ var mechanism = this.parseCString(buffer)
471
+
472
+ if (mechanism) {
473
+ msg.mechanisms.push(mechanism)
474
+ }
475
+ } while (mechanism)
476
+
477
+ return msg
478
+ case 11: // AuthenticationSASLContinue
479
+ msg.name = 'authenticationSASLContinue'
480
+ msg.data = this.readString(buffer, length - 4)
481
+
482
+ return msg
483
+ case 12: // AuthenticationSASLFinal
484
+ msg.name = 'authenticationSASLFinal'
485
+ msg.data = this.readString(buffer, length - 4)
486
+
440
487
  return msg
441
- }
442
488
  }
489
+
443
490
  throw new Error('Unknown authenticationOk message type' + util.inspect(msg))
444
491
  }
445
492
 
package/lib/defaults.js CHANGED
@@ -58,7 +58,13 @@ module.exports = {
58
58
  statement_timeout: false,
59
59
 
60
60
  // max miliseconds to wait for query to complete (client side)
61
- query_timeout: false
61
+ query_timeout: false,
62
+
63
+ connect_timeout: 0,
64
+
65
+ keepalives: 1,
66
+
67
+ keepalives_idle: 0
62
68
  }
63
69
 
64
70
  var pgTypes = require('pg-types')
@@ -139,12 +139,16 @@ NativeQuery.prototype.submit = function (client) {
139
139
  // check if the client has already executed this named query
140
140
  // if so...just execute it again - skip the planning phase
141
141
  if (client.namedQueries[this.name]) {
142
+ if (this.text && client.namedQueries[this.name] !== this.text) {
143
+ const err = new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
144
+ return after(err)
145
+ }
142
146
  return client.native.execute(this.name, values, after)
143
147
  }
144
148
  // plan the named query the first time, then execute it
145
149
  return client.native.prepare(this.name, this.text, values.length, function (err) {
146
150
  if (err) return after(err)
147
- client.namedQueries[self.name] = true
151
+ client.namedQueries[self.name] = self.text
148
152
  return self.native.execute(self.name, values, after)
149
153
  })
150
154
  } else if (this.values) {
package/lib/query.js CHANGED
@@ -148,6 +148,10 @@ Query.prototype.submit = function (connection) {
148
148
  if (typeof this.text !== 'string' && typeof this.name !== 'string') {
149
149
  return new Error('A query must have either text or a name. Supplying neither is unsupported.')
150
150
  }
151
+ const previous = connection.parsedStatements[this.name]
152
+ if (this.text && previous && this.text !== previous) {
153
+ return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
154
+ }
151
155
  if (this.values && !Array.isArray(this.values)) {
152
156
  return new Error('Query values must be an array')
153
157
  }
@@ -190,7 +194,12 @@ Query.prototype.prepare = function (connection) {
190
194
  }
191
195
 
192
196
  if (self.values) {
193
- self.values = self.values.map(utils.prepareValue)
197
+ try {
198
+ self.values = self.values.map(utils.prepareValue)
199
+ } catch (err) {
200
+ this.handleError(err, connection)
201
+ return
202
+ }
194
203
  }
195
204
 
196
205
  // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
package/lib/result.js CHANGED
@@ -12,13 +12,14 @@ var types = require('pg-types')
12
12
  // result object returned from query
13
13
  // in the 'end' event and also
14
14
  // passed as second argument to provided callback
15
- var Result = function (rowMode) {
15
+ var Result = function (rowMode, types) {
16
16
  this.command = null
17
17
  this.rowCount = null
18
18
  this.oid = null
19
19
  this.rows = []
20
20
  this.fields = []
21
21
  this._parsers = []
22
+ this._types = types
22
23
  this.RowCtor = null
23
24
  this.rowAsArray = rowMode === 'array'
24
25
  if (this.rowAsArray) {
@@ -94,11 +95,9 @@ Result.prototype.addFields = function (fieldDescriptions) {
94
95
  for (var i = 0; i < fieldDescriptions.length; i++) {
95
96
  var desc = fieldDescriptions[i]
96
97
  this.fields.push(desc)
97
- var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text')
98
+ var parser = (this._types || types).getTypeParser(desc.dataTypeID, desc.format || 'text')
98
99
  this._parsers.push(parser)
99
100
  }
100
101
  }
101
102
 
102
- Result.prototype._getTypeParser = types.getTypeParser
103
-
104
103
  module.exports = Result
package/lib/sasl.js ADDED
@@ -0,0 +1,146 @@
1
+ const crypto = require('crypto')
2
+
3
+ function startSession (mechanisms) {
4
+ if (mechanisms.indexOf('SCRAM-SHA-256') === -1) {
5
+ throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported')
6
+ }
7
+
8
+ const clientNonce = crypto.randomBytes(18).toString('base64')
9
+
10
+ return {
11
+ mechanism: 'SCRAM-SHA-256',
12
+ clientNonce,
13
+ response: 'n,,n=*,r=' + clientNonce,
14
+ message: 'SASLInitialResponse'
15
+ }
16
+ }
17
+
18
+ function continueSession (session, password, serverData) {
19
+ if (session.message !== 'SASLInitialResponse') {
20
+ throw new Error('SASL: Last message was not SASLInitialResponse')
21
+ }
22
+
23
+ const sv = extractVariablesFromFirstServerMessage(serverData)
24
+
25
+ if (!sv.nonce.startsWith(session.clientNonce)) {
26
+ throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce')
27
+ }
28
+
29
+ var saltBytes = Buffer.from(sv.salt, 'base64')
30
+
31
+ var saltedPassword = Hi(password, saltBytes, sv.iteration)
32
+
33
+ var clientKey = createHMAC(saltedPassword, 'Client Key')
34
+ var storedKey = crypto.createHash('sha256').update(clientKey).digest()
35
+
36
+ var clientFirstMessageBare = 'n=*,r=' + session.clientNonce
37
+ var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration
38
+
39
+ var clientFinalMessageWithoutProof = 'c=biws,r=' + sv.nonce
40
+
41
+ var authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof
42
+
43
+ var clientSignature = createHMAC(storedKey, authMessage)
44
+ var clientProofBytes = xorBuffers(clientKey, clientSignature)
45
+ var clientProof = clientProofBytes.toString('base64')
46
+
47
+ var serverKey = createHMAC(saltedPassword, 'Server Key')
48
+ var serverSignatureBytes = createHMAC(serverKey, authMessage)
49
+
50
+ session.message = 'SASLResponse'
51
+ session.serverSignature = serverSignatureBytes.toString('base64')
52
+ session.response = clientFinalMessageWithoutProof + ',p=' + clientProof
53
+ }
54
+
55
+ function finalizeSession (session, serverData) {
56
+ if (session.message !== 'SASLResponse') {
57
+ throw new Error('SASL: Last message was not SASLResponse')
58
+ }
59
+
60
+ var serverSignature
61
+
62
+ String(serverData).split(',').forEach(function (part) {
63
+ switch (part[0]) {
64
+ case 'v':
65
+ serverSignature = part.substr(2)
66
+ break
67
+ }
68
+ })
69
+
70
+ if (serverSignature !== session.serverSignature) {
71
+ throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match')
72
+ }
73
+ }
74
+
75
+ function extractVariablesFromFirstServerMessage (data) {
76
+ var nonce, salt, iteration
77
+
78
+ String(data).split(',').forEach(function (part) {
79
+ switch (part[0]) {
80
+ case 'r':
81
+ nonce = part.substr(2)
82
+ break
83
+ case 's':
84
+ salt = part.substr(2)
85
+ break
86
+ case 'i':
87
+ iteration = parseInt(part.substr(2), 10)
88
+ break
89
+ }
90
+ })
91
+
92
+ if (!nonce) {
93
+ throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing')
94
+ }
95
+
96
+ if (!salt) {
97
+ throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing')
98
+ }
99
+
100
+ if (!iteration) {
101
+ throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing')
102
+ }
103
+
104
+ return {
105
+ nonce,
106
+ salt,
107
+ iteration
108
+ }
109
+ }
110
+
111
+ function xorBuffers (a, b) {
112
+ if (!Buffer.isBuffer(a)) a = Buffer.from(a)
113
+ if (!Buffer.isBuffer(b)) b = Buffer.from(b)
114
+ var res = []
115
+ if (a.length > b.length) {
116
+ for (var i = 0; i < b.length; i++) {
117
+ res.push(a[i] ^ b[i])
118
+ }
119
+ } else {
120
+ for (var j = 0; j < a.length; j++) {
121
+ res.push(a[j] ^ b[j])
122
+ }
123
+ }
124
+ return Buffer.from(res)
125
+ }
126
+
127
+ function createHMAC (key, msg) {
128
+ return crypto.createHmac('sha256', key).update(msg).digest()
129
+ }
130
+
131
+ function Hi (password, saltBytes, iterations) {
132
+ var ui1 = createHMAC(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])]))
133
+ var ui = ui1
134
+ for (var i = 0; i < iterations - 1; i++) {
135
+ ui1 = createHMAC(password, ui1)
136
+ ui = xorBuffers(ui, ui1)
137
+ }
138
+
139
+ return ui
140
+ }
141
+
142
+ module.exports = {
143
+ startSession,
144
+ continueSession,
145
+ finalizeSession
146
+ }
package/lib/utils.js CHANGED
@@ -97,7 +97,12 @@ function pad (number, digits) {
97
97
 
98
98
  function dateToString (date) {
99
99
  var offset = -date.getTimezoneOffset()
100
- var ret = pad(date.getFullYear(), 4) + '-' +
100
+
101
+ var year = date.getFullYear()
102
+ var isBCYear = year < 1
103
+ if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation
104
+
105
+ var ret = pad(year, 4) + '-' +
101
106
  pad(date.getMonth() + 1, 2) + '-' +
102
107
  pad(date.getDate(), 2) + 'T' +
103
108
  pad(date.getHours(), 2) + ':' +
@@ -110,11 +115,17 @@ function dateToString (date) {
110
115
  offset *= -1
111
116
  } else { ret += '+' }
112
117
 
113
- return ret + pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2)
118
+ ret += pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2)
119
+ if (isBCYear) ret += ' BC'
120
+ return ret
114
121
  }
115
122
 
116
123
  function dateToStringUTC (date) {
117
- var ret = pad(date.getUTCFullYear(), 4) + '-' +
124
+ var year = date.getUTCFullYear()
125
+ var isBCYear = year < 1
126
+ if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation
127
+
128
+ var ret = pad(year, 4) + '-' +
118
129
  pad(date.getUTCMonth() + 1, 2) + '-' +
119
130
  pad(date.getUTCDate(), 2) + 'T' +
120
131
  pad(date.getUTCHours(), 2) + ':' +
@@ -122,7 +133,9 @@ function dateToStringUTC (date) {
122
133
  pad(date.getUTCSeconds(), 2) + '.' +
123
134
  pad(date.getUTCMilliseconds(), 3)
124
135
 
125
- return ret + '+00:00'
136
+ ret += '+00:00'
137
+ if (isBCYear) ret += ' BC'
138
+ return ret
126
139
  }
127
140
 
128
141
  function normalizeQueryConfig (config, values, callback) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pg",
3
- "version": "7.8.1",
3
+ "version": "7.11.0",
4
4
  "description": "PostgreSQL client - pure javascript & libpq with the same API",
5
5
  "keywords": [
6
6
  "database",
package/.travis.yml DELETED
@@ -1,38 +0,0 @@
1
- language: node_js
2
- sudo: false
3
- dist: trusty
4
- before_script:
5
- - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres
6
- env:
7
- - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres
8
-
9
- matrix:
10
- include:
11
- - node_js: "lts/boron"
12
- addons:
13
- postgresql: "9.6"
14
- - node_js: "lts/argon"
15
- addons:
16
- postgresql: "9.6"
17
- - node_js: "10"
18
- addons:
19
- postgresql: "9.6"
20
- - node_js: "lts/carbon"
21
- addons:
22
- postgresql: "9.1"
23
- dist: precise
24
- - node_js: "lts/carbon"
25
- addons:
26
- postgresql: "9.2"
27
- - node_js: "lts/carbon"
28
- addons:
29
- postgresql: "9.3"
30
- - node_js: "lts/carbon"
31
- addons:
32
- postgresql: "9.4"
33
- - node_js: "lts/carbon"
34
- addons:
35
- postgresql: "9.5"
36
- - node_js: "lts/carbon"
37
- addons:
38
- postgresql: "9.6"