Use stRange to provide full-featured Range class #4
Conversation
Which invalid bounds do you have in mind? stRange doesn't enforce only numbers. |
Oh, hi! Just submitted a PR: moll/js-strange#1. |
Anyway, since whether or not to throw an error on invalid bounds seems like an upstream decision, @waisbrot this is ready to merge pending your approval and doc updates. |
Hm, the JSON format actually is a problem. @butterflyhug what do you think? "lower" and "upper" aren't my favorite keys (I always reverse them) but do we really want to have to change all the client code? |
|
There's indeed a handful of synonyms for range endpoints that depend on your axes' angles and context. I'm not against aliases in stRange... |
The |
If we can use the updated library in API v5 and keep the old version in our legacy API v4, I don't think it'd be the end of the world. That change might hit @andrewkhatutsky harder. The web app aggressively upgrade ranges from that JSON format into Twix ranges, so most of our code is isolated from the wire format and we'd only have a focused bit of code to update. If Andrew similarly only deals with the wire format for HTTP requests => insert into Core Data, it might not actually be that bad all around. |
The other thing is that we serialize the range object to JSON to send it to clients (and also clients send us a serialization) so renaming the keys is a pretty big change. |
If I throw an I actually think the math-y serialization format beats the object format for precisely the reason the latter depends on key names. |
Yep, and stRange's toJSON should result in the same Pg compatible format. |
toJSON in stRange, for reference: https://github.com/moll/js-strange/blob/master/index.js#L229-L259 |
Oh, I should actually read your fine documentation instead of just skimming Benesch's tests. Yeah, I agree with you. I do like that more than an object with 2-3 keys. |
I haven't tested current behavior, but // FIXME: How to serialize an empty range with undefined endpoints? worries me, since we regularly serialize ranges with undefined endpoints. |
Right. I just saw that too. I'm glad I made a note of it when I implemented. I see your code previously stringified to |
We never use ranges where both ends are undefined. But are you sure that Postgres won't accept |
Yeah, looks to me like Postgres does accept Postgres uses its string syntax to serialize its ranges to JSON; I think that's another minor data point in favor of stRange's JSON. |
Ah, no, you're right, @waisbrot. I misremembered the Pg syntax. That comment refers to an empty range as opposed to an infinite range. The former Pg seems to represent by the string "empty", rather than something with
|
Ah, right. I don't think there's an alternative syntax for |
A typed language could represent the latter without resorting to English with
|
@moll to respond to your earlier point about aliasing toJSON as toPostgres—that doesn't quite work, because toJSON doesn't handle escaping properly—nor empty ranges. In case you'd be interested in "fixing" this upstream, these are the broken tests: https://travis-ci.org/WhoopInc/node-pg-range/jobs/103925652 |
Actually, I'm not sure this is solvable without |
Ah, in that case, @benesch, indeed. Though, in general, I'm not a fan of the OO |
I see your point, @moll, though I don't think it's particularly worse than littering everything with |
@benesch Safe to use this PR? |
@jpdesigndev kind of. See the test failures here: https://travis-ci.org/WhoopInc/node-pg-range/jobs/103925652. If you don't need empty range support, or support for non-integral ranges, you're safe with this PR. (strange doesn't currently encode tsranges or ranges of custom types properly.) |
I'm not against adding a better serialization format for empty ranges than One quicker "fix" for serializing objects whose |
@moll here's my proposal: this library exposes a If you ever do come up with an alternate approach for Postgres serialization that doesn't require a @jpdesigndev this PR now passes all the tests, so it should be safe to use! |
Sorry, force-pushed for clarity! Here's the diff from the last time you looked at this PR: diff --git a/lib/range.js b/lib/range.js
index 13abd62..7445a3b 100644
--- a/lib/range.js
+++ b/lib/range.js
@@ -1,6 +1,19 @@
var Range = require("strange")
, util = require("util");
+function formatBound(value, prepare) {
+ if (value === null) {
+ return "";
+ }
+
+ value = prepare(value);
+ if (/[()[\],"\\]/.test(value)) {
+ // quote bound only if necessary
+ value = "\"" + value.replace(/(\\|")/, "\\$1") + "\"";
+ }
+ return value;
+}
+
function PGRange(begin, end, bounds) {
if (!(this instanceof PGRange)) {
return new PGRange(begin, end, bounds);
@@ -10,6 +23,16 @@ function PGRange(begin, end, bounds) {
util.inherits(PGRange, Range);
-PGRange.prototype.toPostgres = PGRange.prototype.toJSON;
+PGRange.prototype.toPostgres = function (prepare) {
+ if (this.isEmpty()) {
+ return "empty";
+ }
+
+ return util.format("%s%s,%s%s",
+ this.bounds[0],
+ formatBound(this.begin, prepare),
+ formatBound(this.end, prepare),
+ this.bounds[1]);
+}; Basically this library has always been very anal about properly serializing JavaScript objects into PostgreSQL literals. stRange's Expect to see this land in the next few days unless @moll has some serious concerns! |
Thanks @benesch. This is extremely helpful! |
I'm all game. Implementations we can change anytime. ;) |
Merged in 1.0.0! 🍻 |
WIP. Problems:
Fixes #3.