Range expression update

* Add Int4 and Int8 integer expression to distinguish int4range and int8range types
* Add range functions to range expressions to avoid go template appearing in sql
* Compact range integration tests and add range update tests
This commit is contained in:
go-jet 2024-02-27 10:48:57 +01:00
parent 9d45aaaba5
commit 43fc77ba99
8 changed files with 472 additions and 460 deletions

View file

@ -470,12 +470,12 @@ func REGEXP_LIKE(stringExp StringExpression, pattern StringExpression, matchType
//----------Range Type Functions ----------------------//
// LOWER_BOUND returns range expressions lower bound
// LOWER_BOUND returns range expressions lower bound. Returns null if range is empty or the requested bound is infinite.
func LOWER_BOUND[T Expression](rangeExpression Range[T]) T {
return rangeTypeCaster[T](rangeExpression, NewFunc("LOWER", []Expression{rangeExpression}, nil))
}
// UPPER_BOUND returns range expressions upper bound
// UPPER_BOUND returns range expressions upper bound. Returns null if range is empty or the requested bound is infinite.
func UPPER_BOUND[T Expression](rangeExpression Range[T]) T {
return rangeTypeCaster[T](rangeExpression, NewFunc("UPPER", []Expression{rangeExpression}, nil))
}
@ -483,18 +483,45 @@ func UPPER_BOUND[T Expression](rangeExpression Range[T]) T {
func rangeTypeCaster[T Expression](rangeExpression Range[T], exp Expression) T {
var i Expression
switch rangeExpression.(type) {
case Range[Int4Expression], Range[Int8Expression]:
i = IntExp(exp)
case Range[NumericExpression]:
i = FloatExp(exp)
case Range[DateExpression]:
i = DateExp(exp)
case Range[IntegerExpression]:
i = IntExp(exp)
case Range[TimestampzExpression]:
i = TimestampzExp(exp)
case Range[TimestampExpression]:
i = TimestampExp(exp)
case Range[TimestampzExpression]:
i = TimestampzExp(exp)
}
return i.(T)
}
// IS_EMPTY returns true if range is empty
func IS_EMPTY[T Expression](rangeExpression Range[T]) BoolExpression {
return newBoolFunc("ISEMPTY", rangeExpression)
}
// LOWER_INC returns true if lower bound is inclusive. Returns false for empty range.
func LOWER_INC[T Expression](rangeExpression Range[T]) BoolExpression {
return newBoolFunc("LOWER_INC", rangeExpression)
}
// UPPER_INC returns true if upper bound is inclusive. Returns false for empty range.
func UPPER_INC[T Expression](rangeExpression Range[T]) BoolExpression {
return newBoolFunc("UPPER_INC", rangeExpression)
}
// LOWER_INF returns true if upper bound is infinite. Returns false for empty range.
func LOWER_INF[T Expression](rangeExpression Range[T]) BoolExpression {
return newBoolFunc("LOWER_INF", rangeExpression)
}
// UPPER_INF returns true if lower bound is infinite. Returns false for empty range.
func UPPER_INF[T Expression](rangeExpression Range[T]) BoolExpression {
return newBoolFunc("UPPER_INF", rangeExpression)
}
//----------Data Type Formatting Functions ----------------------//
// TO_CHAR converts expression to string with format
@ -872,30 +899,30 @@ func Func(name string, expressions ...Expression) Expression {
}
func NumRange(lowNum, highNum NumericExpression, bounds ...StringExpression) Range[NumericExpression] {
return RangeExp[NumericExpression](NewFunc("numrange", rangeFuncParamCombiner[NumericExpression](lowNum, highNum, bounds...), nil))
return NumRangeExp(NewFunc("numrange", rangeFuncParamCombiner(lowNum, highNum, bounds...), nil))
}
func Int4Range(lowNum, highNum IntegerExpression, bounds ...StringExpression) Range[IntegerExpression] {
return RangeExp[IntegerExpression](NewFunc("int4range", rangeFuncParamCombiner[IntegerExpression](lowNum, highNum, bounds...), nil))
func Int4Range(lowNum, highNum IntegerExpression, bounds ...StringExpression) Range[Int4Expression] {
return Int4RangeExp(NewFunc("int4range", rangeFuncParamCombiner(lowNum, highNum, bounds...), nil))
}
func Int8Range(lowNum, highNum IntegerExpression, bounds ...StringExpression) Range[IntegerExpression] {
return RangeExp[IntegerExpression](NewFunc("int8range", rangeFuncParamCombiner[IntegerExpression](lowNum, highNum, bounds...), nil))
func Int8Range(lowNum, highNum Int8Expression, bounds ...StringExpression) Range[Int8Expression] {
return Int8RangeExp(NewFunc("int8range", rangeFuncParamCombiner(lowNum, highNum, bounds...), nil))
}
func TimestampRange(lowTs, highTs TimestampExpression, bounds ...StringExpression) Range[TimestampExpression] {
return RangeExp[TimestampExpression](NewFunc("tsrange", rangeFuncParamCombiner[TimestampExpression](lowTs, highTs, bounds...), nil))
func TsRange(lowTs, highTs TimestampExpression, bounds ...StringExpression) Range[TimestampExpression] {
return TsRangeExp(NewFunc("tsrange", rangeFuncParamCombiner(lowTs, highTs, bounds...), nil))
}
func TimestampzRange(lowTs, highTs TimestampzExpression, bounds ...StringExpression) Range[TimestampzExpression] {
return RangeExp[TimestampzExpression](NewFunc("tstzrange", rangeFuncParamCombiner[TimestampzExpression](lowTs, highTs, bounds...), nil))
func TstzRange(lowTs, highTs TimestampzExpression, bounds ...StringExpression) Range[TimestampzExpression] {
return TstzRangeExp(NewFunc("tstzrange", rangeFuncParamCombiner(lowTs, highTs, bounds...), nil))
}
func DateRange(lowTs, highTs DateExpression, bounds ...StringExpression) Range[DateExpression] {
return RangeExp[DateExpression](NewFunc("daterange", rangeFuncParamCombiner[DateExpression](lowTs, highTs, bounds...), nil))
return DateRangeExp(NewFunc("daterange", rangeFuncParamCombiner(lowTs, highTs, bounds...), nil))
}
func rangeFuncParamCombiner[T Expression](low, high T, bounds ...StringExpression) []Expression {
func rangeFuncParamCombiner(low, high Expression, bounds ...StringExpression) []Expression {
exp := []Expression{low, high}
if len(bounds) != 0 {
exp = append(exp, bounds[0])

View file

@ -31,6 +31,12 @@ type IntegerExpression interface {
BIT_SHIFT_RIGHT(shift IntegerExpression) IntegerExpression
}
// additional integer expression subtypes, used in range expressions.
type (
Int4Expression IntegerExpression
Int8Expression IntegerExpression
)
type integerInterfaceImpl struct {
numericExpressionImpl
parent IntegerExpression

View file

@ -18,10 +18,18 @@ type Range[T Expression] interface {
UNION(rhs Range[T]) Range[T]
INTERSECTION(rhs Range[T]) Range[T]
DIFFERENCE(rhs Range[T]) Range[T]
UPPER_BOUND() T
LOWER_BOUND() T
IS_EMPTY() BoolExpression
LOWER_INC() BoolExpression
UPPER_INC() BoolExpression
LOWER_INF() BoolExpression
UPPER_INF() BoolExpression
}
type rangeInterfaceImpl[T Expression] struct {
parent Expression
parent Range[T]
}
func (r *rangeInterfaceImpl[T]) EQ(rhs Range[T]) BoolExpression {
@ -74,6 +82,34 @@ func (r *rangeInterfaceImpl[T]) DIFFERENCE(rhs Range[T]) Range[T] {
return RangeExp[T](Sub(r.parent, rhs))
}
func (r *rangeInterfaceImpl[T]) UPPER_BOUND() T {
return UPPER_BOUND(r.parent)
}
func (r *rangeInterfaceImpl[T]) LOWER_BOUND() T {
return LOWER_BOUND(r.parent)
}
func (r *rangeInterfaceImpl[T]) IS_EMPTY() BoolExpression {
return IS_EMPTY(r.parent)
}
func (r *rangeInterfaceImpl[T]) LOWER_INC() BoolExpression {
return LOWER_INC(r.parent)
}
func (r *rangeInterfaceImpl[T]) UPPER_INC() BoolExpression {
return UPPER_INC(r.parent)
}
func (r *rangeInterfaceImpl[T]) LOWER_INF() BoolExpression {
return LOWER_INF(r.parent)
}
func (r *rangeInterfaceImpl[T]) UPPER_INF() BoolExpression {
return UPPER_INF(r.parent)
}
//---------------------------------------------------//
type rangeExpressionWrapper[T Expression] struct {
@ -93,3 +129,13 @@ func newRangeExpressionWrap[T Expression](expression Expression) Range[T] {
func RangeExp[T Expression](expression Expression) Range[T] {
return newRangeExpressionWrap[T](expression)
}
// different range expression wrappers
var (
Int4RangeExp = RangeExp[Int4Expression]
Int8RangeExp = RangeExp[Int8Expression]
NumRangeExp = RangeExp[NumericExpression]
DateRangeExp = RangeExp[DateExpression]
TsRangeExp = RangeExp[TimestampExpression]
TstzRangeExp = RangeExp[TimestampzExpression]
)

View file

@ -25,7 +25,7 @@ var (
table1ColTimestampz = TimestampzColumn("col_timestampz")
table1ColBool = BoolColumn("col_bool")
table1ColDate = DateColumn("col_date")
table1ColRange = RangeColumn[IntegerExpression]("col_range")
table1ColRange = RangeColumn[Int8Expression]("col_range")
)
var table1 = NewTable("db", "table1", "", table1Col1, table1ColInt, table1ColFloat, table1Col3, table1ColTime, table1ColTimez, table1ColBool, table1ColDate, table1ColRange, table1ColTimestamp, table1ColTimestampz)
@ -41,7 +41,7 @@ var (
table2ColTimestamp = TimestampColumn("col_timestamp")
table2ColTimestampz = TimestampzColumn("col_timestampz")
table2ColDate = DateColumn("col_date")
table2ColRange = RangeColumn[IntegerExpression]("col_range")
table2ColRange = RangeColumn[Int8Expression]("col_range")
)
var table2 = NewTable("db", "table2", "", table2Col3, table2Col4, table2ColInt, table2ColFloat, table2ColStr, table2ColBool, table2ColTime, table2ColTimez, table2ColDate, table2ColRange, table2ColTimestamp, table2ColTimestampz)