pg
                                
                                 pg copied to clipboard
                                
                                    pg copied to clipboard
                            
                            
                            
                        Does it support range type?
If support, how to use
Sorry, I forgot to reply to this one :/ Anyway there is no any support for range types and the biggest problem for adding support for range types is that I don't know how to represent range types in Go... Do you have any ideas?
How about using struct tags to divide the range into two parts? You could for example use ",lower" and ",upper" in this way:
type MyRanges struct{
    Id `pg:"myrangeid"`
    AgeLower `pg:"agerange,lower"`
    AgeUpper `pg:"agerange,upper"`
}
Another idea could be to use a range interface for each type (int, tzrange and so on)
type interface IntRange {
    SetRange(lower, upper int){}
    Range() (int, int) {}
}
type MyRanges struct {
    Id int `pg:"myrangeid"`
    AgeRange IntRange `pg:"agerange"`
}
Forgot about inclusive/exclusive and infinity ranges. Maybe infinity could be handle by the types built in max/min values ( math.MaxInt32 and so on?).
For inclusive/exclusive its trickier. Tags get a bit complicated:
type MyRanges struct{
    Id `pg:"myrangeid"`
    AgeLower `pg:"agerange,lower"`
    AgeLowerInc bool `pg:"agerange,lower_inc"`
    AgeUpper `pg:"agerange,upper"`
    AgeUpperInc bool `pg:"agerange,upper_inc"`
}
But interface is also a bit more complicated:
type interface IntRange {
    SetRange(lower, upper int, lowerInc, upperInc bool){}
    Range() (int, int, bool, bool) {} // Is this ugly? maybe better with 4 separate functions?
}
type MyRanges struct {
    Id int `pg:"myrangeid"`
    AgeRange IntRange `pg:"agerange"`
}
@vmihailenco I think we can use array. Example: [2]int [0] => lower value [1] => upper value
Is the question still open?
Is the question still open?
I am currently in need of a tstzrange (no other ranges). This had me looking into how jackc/pgtype achieved ranged timestamps.
Infinity and beyond:
pg.NullTime would require support for special values, see postgresql doc section 8.5.1.4 . For a quick start, the special values for pos/neg infinity should be enough. The NullTime struct could have a member flag reflecting if it is a special value. Support could be quite easily implemented in types.ParseTimeString and types.AppendTime.
Boundaries:
Ranged type upper and lower values are bounded, mainly inclusive or exclusive, but also unbounded in case of usage of pos/neg infinity, see postgresql doc section 8.17.3 and 8.17.4. The contributors of jackc/pgtype have done it so that they keep track of the boundary types in struct members of the range types.
Range types:
@vmihailenco
... I don't know how to represent range types in Go... Do you have any ideas?
No i do not, but the guys at jackc/pgtypes had an idea. The ranged types there have upper/lower-named struct members of the underlying range type.. The interesting (cannot comment whether that is good or not) part is, that they have a base struct
type UntypedTextRange struct {
	Lower     string
	Upper     string
	lowerType BoundType
	upperType BoundType
}
(see range.go) into which they decode all range types. Then they pass the lower/upper strings to the decoding function of the underlying range type.
Future:
I am currently hacking a quick POC ripping off some of the jackc/pgtype code to see if i understand the stuff correctly. As said, this is just a tstzrange type (all i need) using scanner/valuer.
What is your plan, @vmihailenco? Are you tempted by ranged types or is this something you are indifferent about?
Since i lack your understanding of go-pg/pg i can currently only hope to produce some bastard-code that 'sort of works for me'. If you are interested in range types and if you think that something related to the jackc/pgtype approach would be ok with you, please say so. I could then try to integrate my POC with go-pg/pg instead of just having some extra package providing a (partly redundant) custom type.
The interesting (cannot comment whether that is good or not)
I can't tell whether it is good or not too until I try it. And I won't try it until I have a use case for it. So in practice I can't offer much help except with existing go-pg code and general code review.
the jackc/pgtype
It looks like jackc/pgtype already supports database/sql interfaces. So the chances are you can already use it with go-pg.
I could then try to integrate my POC with go-pg/pg instead of just having some extra package providing a (partly redundant) custom type.
I don't have time to work on this myself, but if you need code review - just ping me. And I don't think that extra packages are bad or inefficient in any sense. On the contrary they allow to develop independent features without any communication / organization overhead. If there are specific things I can do to ease development of 3rd party plugins - let me know and I will try to help.
It looks like jackc/pgtype already supports database/sql interfaces. So the chances are you can already use it with go-pg.
Oh thank God for a solution. I've tested, and yes jackc/pgtype works out of the box with go-pg. I'm now assigning the type pgtype.Tstzrange type to a struct field (ie. column), and using their API to read and write the lower and upper ranges as well as the inclusive/exlusive flags. At least for my use case, so far the integration is flawless. Once you figure out the Status field of both the range as a whole as well as the individual Lower.Status and Upper.Status fields, it's smooth sailing!
It sounds nice that jackc/pgtype works with go-pg but I just wondering if it is good idea to add it with lot of unnecessary dependency. Date and timestamp ranges are quite popular and it will be nice if go-pg can support them.