mirror of
https://github.com/brianc/node-postgres.git
synced 2025-12-08 20:16:25 +00:00
allow type-coercion overrides for custom objects
Attempt to call a `toPostgres` method on objects passed as query values before converting them to JSON. This allows custom types to convert themselves to the appropriate PostgreSQL literal. This strategy is fully backwards-compatible and uses the same pattern as the `toJSON` override.
This commit is contained in:
parent
c41eedc3e0
commit
6ced524390
17
lib/utils.js
17
lib/utils.js
@ -41,7 +41,7 @@ function arrayString(val) {
|
||||
//to their 'raw' counterparts for use as a postgres parameter
|
||||
//note: you can override this function to provide your own conversion mechanism
|
||||
//for complex types, etc...
|
||||
var prepareValue = function(val) {
|
||||
var prepareValue = function(val, seen) {
|
||||
if (val instanceof Buffer) {
|
||||
return val;
|
||||
}
|
||||
@ -55,11 +55,24 @@ var prepareValue = function(val) {
|
||||
return null;
|
||||
}
|
||||
if(typeof val === 'object') {
|
||||
return JSON.stringify(val);
|
||||
return prepareObject(val, seen);
|
||||
}
|
||||
return val.toString();
|
||||
};
|
||||
|
||||
function prepareObject(val, seen) {
|
||||
if(val.toPostgres && typeof val.toPostgres === 'function') {
|
||||
seen = seen || [];
|
||||
if (seen.indexOf(val) !== -1) {
|
||||
throw new Error('circular reference detected while preparing "' + val + '" for query');
|
||||
}
|
||||
seen.push(val);
|
||||
|
||||
return prepareValue(val.toPostgres(), seen);
|
||||
}
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
|
||||
function dateToString(date) {
|
||||
function pad(number, digits) {
|
||||
number = ""+number;
|
||||
|
||||
@ -119,3 +119,43 @@ test('prepareValue: arbitrary objects prepared properly', function() {
|
||||
var out = utils.prepareValue({ x: 42 });
|
||||
assert.strictEqual(out, '{"x":42}');
|
||||
});
|
||||
|
||||
test('prepareValue: objects with simple toPostgres prepared properly', function() {
|
||||
var customType = {
|
||||
toPostgres: function() {
|
||||
return "zomgcustom!";
|
||||
}
|
||||
};
|
||||
var out = utils.prepareValue(customType);
|
||||
assert.strictEqual(out, "zomgcustom!");
|
||||
});
|
||||
|
||||
test('prepareValue: objects with complex toPostgres prepared properly', function() {
|
||||
var buf = new Buffer("zomgcustom!");
|
||||
var customType = {
|
||||
toPostgres: function() {
|
||||
return [1, 2];
|
||||
}
|
||||
};
|
||||
var out = utils.prepareValue(customType);
|
||||
assert.strictEqual(out, '{"1","2"}');
|
||||
});
|
||||
|
||||
test('prepareValue: objects with circular toPostgres rejected', function() {
|
||||
var buf = new Buffer("zomgcustom!");
|
||||
var customType = {
|
||||
toPostgres: function() {
|
||||
return { toPostgres: function () { return customType; } };
|
||||
}
|
||||
};
|
||||
|
||||
//can't use `assert.throws` since we need to distinguish circular reference
|
||||
//errors from call stack exceeded errors
|
||||
try {
|
||||
utils.prepareValue(customType);
|
||||
} catch (e) {
|
||||
assert.ok(e.message.match(/circular/), "Expected circular reference error but got " + e);
|
||||
return;
|
||||
}
|
||||
throw new Error("Expected prepareValue to throw exception");
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user