Fix range types not clearing unbounded or empty

query-exec-mode
Jack Christensen 2022-02-08 16:48:17 -06:00
parent 0306ce3a19
commit f861d83a17
4 changed files with 102 additions and 1 deletions

View File

@ -29,7 +29,8 @@ type RangeScanner interface {
ScanBounds() (lowerTarget, upperTarget interface{})
// SetBoundTypes sets the lower and upper bound types. ScanBounds will be called and the returned values scanned
// (if appropriate) before SetBoundTypes is called.
// (if appropriate) before SetBoundTypes is called. If the bound types are unbounded or empty this method must
// also set the bound values.
SetBoundTypes(lower, upper BoundType) error
}

View File

@ -63,6 +63,58 @@ func TestRangeCodecTranscodeCompatibleRangeElementTypes(t *testing.T) {
})
}
func TestRangeCodecScanRangeTwiceWithUnbounded(t *testing.T) {
conn := testutil.MustConnectPgx(t)
defer testutil.MustCloseContext(t, conn)
var r pgtype.Int4range
err := conn.QueryRow(context.Background(), `select '[1,5)'::int4range`).Scan(&r)
require.NoError(t, err)
require.Equal(
t,
pgtype.Int4range{
Lower: pgtype.Int4{Int: 1, Valid: true},
Upper: pgtype.Int4{Int: 5, Valid: true},
LowerType: pgtype.Inclusive,
UpperType: pgtype.Exclusive,
Valid: true,
},
r,
)
err = conn.QueryRow(context.Background(), `select '[1,)'::int4range`).Scan(&r)
require.NoError(t, err)
require.Equal(
t,
pgtype.Int4range{
Lower: pgtype.Int4{Int: 1, Valid: true},
Upper: pgtype.Int4{},
LowerType: pgtype.Inclusive,
UpperType: pgtype.Unbounded,
Valid: true,
},
r,
)
err = conn.QueryRow(context.Background(), `select 'empty'::int4range`).Scan(&r)
require.NoError(t, err)
require.Equal(
t,
pgtype.Int4range{
Lower: pgtype.Int4{},
Upper: pgtype.Int4{},
LowerType: pgtype.Empty,
UpperType: pgtype.Empty,
Valid: true,
},
r,
)
}
func TestRangeCodecDecodeValue(t *testing.T) {
conn := testutil.MustConnectPgx(t)
defer testutil.MustCloseContext(t, conn)

View File

@ -31,6 +31,12 @@ func (r *Int4range) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Int4range) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Int4{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Int4{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -67,6 +73,12 @@ func (r *Int8range) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Int8range) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Int8{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Int8{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -103,6 +115,12 @@ func (r *Numrange) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Numrange) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Numeric{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Numeric{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -139,6 +157,12 @@ func (r *Tsrange) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Tsrange) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Timestamp{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Timestamp{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -175,6 +199,12 @@ func (r *Tstzrange) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Tstzrange) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Timestamptz{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Timestamptz{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -211,6 +241,12 @@ func (r *Daterange) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Daterange) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Date{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Date{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
@ -247,6 +283,12 @@ func (r *Float8range) ScanBounds() (lowerTarget, upperTarget interface{}) {
}
func (r *Float8range) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = Float8{}
}
if upper == Unbounded || upper == Empty {
r.Upper = Float8{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true

View File

@ -41,6 +41,12 @@ func (r *<%= range_type %>) ScanBounds() (lowerTarget, upperTarget interface{})
}
func (r *<%= range_type %>) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
r.Lower = <%= element_type %>{}
}
if upper == Unbounded || upper == Empty {
r.Upper = <%= element_type %>{}
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true