brianc/node-postgres — pull request #555 by benesch (2014-03-30 23:49:03+00:00)
Title: Supercharge `prepareValue`

This PR addresses a few small issues:

1. `utils.prepareValue` didn't have unit tests for existing functionality. Now it does!
1. `utils.prepareValue` appears to have grown organically over the past few years, so the conditional wasn't
1. Arrays of dates were always converted to UTC, while single dates properly had the local timezone offset appended thanks to bde87170. `arrayString` duplicated `prepareValue`'s logic and so didn't get the fixed. I've refactored `arrayString` to drop down to `prepareValue` whenever possible so hopefully this doesn't happen again!
1. Arrays of objects (Postgres type `json[]`) were improperly escaped. The fix for #3 actually fixed this too.

And one big one:

0008c53 adds support for a `toPostgres` method, a la `toJSON`. If an object passed to `prepareValue` has a function property called `toPostgres`, it's invoked and the return value is used in place of `JSON.stringify`. The value returned by an object's `toPostgres` is passed to `prepareValue` recursively, so `toPostgres` doesn't need to return a Postgres literal, just a more primitive JS type.

For context, I've been trying to implement support for range types. Parsing range literals into objects on the way out couldn't be easier (thanks!), but there's no sane way to override `utils.prepareValue` to convert a JS range object to a Postgres range literal.

`toPostgres` is the simplest strategy for custom type-coercion on the way in I could think of. A type registry—register preparers for JS types—is tricky because JS's `instanceof` operator fails hard. Supporting multiple `prepareValue` handlers is possible, but ordering would be a nightmare. Would love to hear your thoughts!

I've tried to split my commits sensibly so you can pick-and-choose as you see fit. Cheers!