João Eudes Lima
10/29/2024, 1:18 AMfun distance(
lat: Double,
lon: Double,
latColumn: Expression<Double>,
lonColumn: Expression<Double>
) {
val radius = PI / 180
val radiusLiteral = doubleParam(radius)
val radLat = doubleParam(lat * radius) // Precomputed latitude in radians
val radLon = doubleParam(lon * radius) // Precomputed longitude in radians
val earthRadiusKmLiteral = doubleParam(6371.0) // Earth radius in kilometers
Expression.build {
acos(
cos(radLat) *
cos(latColumn * radiusLiteral) *
cos((lonColumn * radiusLiteral) - radLon) +
sin(radLat) *
sin(latColumn * radiusLiteral)
) * earthRadiusKmLiteral
}
}
Chantal Loncle
10/29/2024, 2:58 AMExpressionWithColumnType
(like actual columns and doubleLiteral()
), as do most infix operators. These built-in trig functions also use DecimalColumnType
under the hood.
So if you want to be using specifically un-column-typed expressions with doubleParam()
, you can implement less restrictive versions in any way you want. For example, I've chosen to not use extension functions below for more readability:
fun <T : Double?> acos(expr: Expression<T>): CustomFunction<Double?> =
CustomFunction("ACOS", DoubleColumnType(), expr)
fun <T : Double?> cos(expr: Expression<T>): CustomFunction<Double?> =
CustomFunction("COS", DoubleColumnType(), expr)
fun <T : Double?> sin(expr: Expression<T>): CustomFunction<Double?> =
CustomFunction("SIN", DoubleColumnType(), expr)
infix operator fun Expression<Double>.times(other: Expression<Double>): TimesOp<Double, Double> = TimesOp(this, other, DoubleColumnType())
Then your final block above would look like this:
acos(
cos(radLat)
.times(cos(latColumn * radiusLiteral))
.times(cos((lonColumn * radiusLiteral) - radLon))
.plus(sin(radLat))
.times(sin(latColumn * radiusLiteral))
) * earthRadiusKmLiteral
João Eudes Lima
11/01/2024, 12:09 PM