Skip to content

Commit 4225f56

Browse files
committed
Merge branch 'master' of https://github.com/brianc/node-postgres into brianc-master
Conflicts: lib/defaults.js
2 parents eb9727a + 93aa52d commit 4225f56

File tree

10 files changed

+109
-15
lines changed

10 files changed

+109
-15
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req
44

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

7+
### v4.5.0
8+
- Add option to parse JS date objects in query parameters as [UTC](https://github.com/brianc/node-postgres/pull/943)
9+
710
### v4.4.0
811
- Warn to `stderr` if a named query exceeds 63 characters which is the max lenght supported by postgres.
912

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,14 @@ node-postgres is by design pretty light on abstractions. These are some handy m
147147
- [iceddev/pg-transact](https://github.com/iceddev/pg-transact) - A nicer API on node-postgres transactions
148148
- [sehrope/node-pg-db](https://github.com/sehrope/node-pg-db) - Simpler interface, named parameter support, transaction management and event hooks.
149149
- [vitaly-t/pg-promise](https://github.com/vitaly-t/pg-promise) - Use node-postgres via [Promises/A+](https://promisesaplus.com/).
150+
- [kriasoft/node-pg-client](https://github.com/kriasoft/node-pg-client) - Promise-based wrapper for `node-postgres` designed for easy use with ES7 async/await.
150151
- [pg-then](https://github.com/coderhaoxin/pg-then) A tiny wrapper of `pg` for promise api.
152+
- [pg-rxjs](https://github.com/jadbox/pg-rxjs) Another tiny wrapper like `pg-then` but for [RxJS](https://github.com/Reactive-Extensions/RxJS)
151153
- [acarl/pg-restify](https://github.com/acarl/pg-restify) - Creates a generic REST API for a postgres database using restify.
152154
- [XeCycle/pg-template-tag](https://github.com/XeCycle/pg-template-tag) - Write queries with ES6 tagged template literals, a "poor man's query builder".
153155
- [recursivefunk/pg-gen](https://github.com/recursivefunk/pg-gen) - Use ES6 Generators to paginate through large Postgres result sets
156+
- [vitaly-t/pg-minify](https://github.com/vitaly-t/pg-minify) - Minifies PostgreSQL scripts.
157+
- [MassiveJS](https://github.com/robconery/massive-js) - A simple relational data access tool that has full JSONB document support for Postgres.
154158

155159
## License
156160

lib/defaults.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ var defaults = module.exports = {
4040

4141
ssl: false,
4242

43-
application_name : undefined,
43+
application_name: undefined,
4444
fallback_application_name: undefined,
4545

46-
//heartbeat interval to check, that socket is alive. if 0 - heartbeat is disabled (for backward capability).
47-
//else - timeout in ms.
48-
heartbeat_interval: 0
46+
parseInputDatesAsUTC: false
4947
};
5048

5149
//parse int8 so you can get your count values as actual numbers

lib/native/result.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ NativeResult.prototype.addCommandComplete = function(pq) {
1919
});
2020
}
2121
};
22+
23+
NativeResult.prototype.addRow = function(row) {
24+
// This is empty to ensure pg code doesn't break when switching to pg-native
25+
// pg-native loads all rows into the final result object by default.
26+
// This is because libpg loads all rows into memory before passing the result
27+
// to pg-native.
28+
};

lib/result.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ var inlineParser = function(fieldName, i) {
7070
//fields containing single quotes will break
7171
//the evaluated javascript unless they are escaped
7272
//see https://github.com/brianc/node-postgres/issues/507
73-
fieldName.replace("'", "\\'") +
73+
//Addendum: However, we need to make sure to replace all
74+
//occurences of apostrophes, not just the first one.
75+
//See https://github.com/brianc/node-postgres/issues/934
76+
fieldName.replace(/'/g, "\\'") +
7477
"'] = " +
7578
"rowData[" + i + "] == null ? null : parsers[" + i + "](rowData[" + i + "]);";
7679
};

lib/utils.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
var defaults = require('./defaults');
12

23
// convert a JS array to a postgres array literal
34
// uses comma separator so won't work for types like box that use
@@ -32,7 +33,11 @@ var prepareValue = function(val, seen) {
3233
return val;
3334
}
3435
if(val instanceof Date) {
35-
return dateToString(val);
36+
if(defaults.parseInputDatesAsUTC) {
37+
return dateToStringUTC(val);
38+
} else {
39+
return dateToString(val);
40+
}
3641
}
3742
if(Array.isArray(val)) {
3843
return arrayString(val);
@@ -59,13 +64,14 @@ function prepareObject(val, seen) {
5964
return JSON.stringify(val);
6065
}
6166

67+
function pad(number, digits) {
68+
number = "" +number;
69+
while(number.length < digits)
70+
number = "0" + number;
71+
return number;
72+
}
73+
6274
function dateToString(date) {
63-
function pad(number, digits) {
64-
number = ""+number;
65-
while(number.length < digits)
66-
number = "0"+number;
67-
return number;
68-
}
6975

7076
var offset = -date.getTimezoneOffset();
7177
var ret = pad(date.getFullYear(), 4) + '-' +
@@ -86,6 +92,19 @@ function dateToString(date) {
8692
return ret + pad(Math.floor(offset/60), 2) + ":" + pad(offset%60, 2);
8793
}
8894

95+
function dateToStringUTC(date) {
96+
97+
var ret = pad(date.getUTCFullYear(), 4) + '-' +
98+
pad(date.getUTCMonth() + 1, 2) + '-' +
99+
pad(date.getUTCDate(), 2) + 'T' +
100+
pad(date.getUTCHours(), 2) + ':' +
101+
pad(date.getUTCMinutes(), 2) + ':' +
102+
pad(date.getUTCSeconds(), 2) + '.' +
103+
pad(date.getUTCMilliseconds(), 3);
104+
105+
return ret + "+00:00";
106+
}
107+
89108
function normalizeQueryConfig (config, values, callback) {
90109
//can take in strings or config objects
91110
config = (typeof(config) == 'string') ? { text: config } : config;
@@ -103,6 +122,10 @@ function normalizeQueryConfig (config, values, callback) {
103122
}
104123

105124
module.exports = {
106-
prepareValue: prepareValue,
125+
prepareValue: function prepareValueWrapper (value) {
126+
//this ensures that extra arguments do not get passed into prepareValue
127+
//by accident, eg: from calling values.map(utils.prepareValue)
128+
return prepareValue(value);
129+
},
107130
normalizeQueryConfig: normalizeQueryConfig
108131
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg",
3-
"version": "4.4.3",
3+
"version": "4.5.1",
44
"description": "PostgreSQL client - pure javascript & libpq with the same API",
55
"keywords": [
66
"postgres",
@@ -18,7 +18,7 @@
1818
"author": "Brian Carlson <brian.m.carlson@gmail.com>",
1919
"main": "./lib",
2020
"dependencies": {
21-
"buffer-writer": "1.0.0",
21+
"buffer-writer": "1.0.1",
2222
"generic-pool": "2.1.1",
2323
"packet-reader": "0.2.0",
2424
"pg-connection-string": "0.1.3",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var helper = require(__dirname + '/../test-helper');
2+
var pg = helper.pg;
3+
4+
test('support for complex column names', function() {
5+
pg.connect(helper.config, assert.success(function(client, done) {
6+
client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )");
7+
client.query('SELECT * FROM t', assert.success(function(res) {
8+
done();
9+
assert.strictEqual(res.fields[0].name, "complex''column");
10+
pg.end();
11+
}));
12+
}));
13+
});

test/integration/client/simple-query-tests.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ test("simple query interface", function() {
3636
});
3737
});
3838

39+
test("simple query interface using addRow", function() {
40+
41+
var client = helper.client();
42+
43+
var query = client.query("select name from person order by name");
44+
45+
client.on('drain', client.end.bind(client));
46+
47+
query.on('row', function(row, result) {
48+
assert.ok(result);
49+
result.addRow(row);
50+
});
51+
52+
query.on('end', function(result) {
53+
assert.lengthIs(result.rows, 26, "result returned wrong number of rows");
54+
assert.lengthIs(result.rows, result.rowCount);
55+
assert.equal(result.rows[0].name, "Aaron");
56+
assert.equal(result.rows[25].name, "Zanzabar");
57+
});
58+
});
59+
3960
test("multiple simple queries", function() {
4061
var client = helper.client();
4162
client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"})

test/unit/utils-tests.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ test('prepareValues: date prepared properly', function() {
6565
helper.resetTimezoneOffset();
6666
});
6767

68+
test('prepareValues: date prepared properly as UTC', function() {
69+
defaults.parseInputDatesAsUTC = true;
70+
71+
// make a date in the local timezone that represents a specific UTC point in time
72+
var date = new Date(Date.UTC(2014, 1, 1, 11, 11, 1, 7));
73+
var out = utils.prepareValue(date);
74+
assert.strictEqual(out, "2014-02-01T11:11:01.007+00:00");
75+
76+
defaults.parseInputDatesAsUTC = false;
77+
});
78+
6879
test('prepareValues: undefined prepared properly', function() {
6980
var out = utils.prepareValue(void 0);
7081
assert.strictEqual(out, null);
@@ -171,3 +182,14 @@ test('prepareValue: objects with circular toPostgres rejected', function() {
171182
}
172183
throw new Error("Expected prepareValue to throw exception");
173184
});
185+
186+
test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function() {
187+
var customType = {
188+
toPostgres: function() {
189+
return "zomgcustom!";
190+
}
191+
};
192+
var values = [1, "test", customType]
193+
var out = values.map(utils.prepareValue)
194+
assert.deepEqual(out, [1, "test", "zomgcustom!"])
195+
})

0 commit comments

Comments
 (0)