jetbrains exposed - select based on nullable reference column - kotlin

I'm trying to select the rows from a table based on a nullable referenced column.
If you replace the reference with just a standard integer column and keep it nullable, it handles the eq just fine. I've also tried replacing the reference with optReference, but that didn't make a difference.
The error is given by the compiler.
None of the following functions can be called with the arguments supplied.
Expression<in EntityID<Int>?>.eq(Expression<in EntityID<Int>?>)   where T = EntityID<Int>?, S1 = EntityID<Int>?, S2 = EntityID<Int>? for   infix fun <T, S1 : T?, S2 : T?> Expression<in S1>.eq(other: Expression<in S2>): Op<Boolean> defined in org.jetbrains.exposed.sql.SqlExpressionBuilder
ExpressionWithColumnType<T>.eq(T)   where T cannot be inferred for   infix fun <T> ExpressionWithColumnType<T>.eq(t: T): Op<Boolean> defined in org.jetbrains.exposed.sql.SqlExpressionBuilder
ExpressionWithColumnType<EntityID<Int>>.eq(Int?)   where T = Int for   infix fun <T : Comparable<T>> ExpressionWithColumnType<EntityID<T>>.eq(t: T?): Op<Boolean> defined in org.jetbrains.exposed.sql.SqlExpressionBuilder
A basic working example showing the error given by Intellij.
object A : IntIdTable("a") {
val n = varchar("n", 255)
val x = reference("x", B).nullable()
}
object B : IntIdTable("b") {
val i = varchar("m", 255)
val y = integer("y")
}
fun main() {
connectToDatabase()
transaction {
SchemaUtils.createMissingTablesAndColumns(A, B)
A.select { A.x eq 1 }
}
}
The equivalent sql I'm want it to run is:
select * from test.a as a where a.x = 1;

A.x is not a Column<Int>, its type is actually Column<EntityID<Int>>.
It looks like you need to write the query as
A.select { A.x eq EntityID(1, B) }

Related

Generic Kotlin factory to DRY constructor parameters

I have the following simple class hierarchy.
abstract class B {
abstract val o : Int
}
class D1 (m: Int, n: Int) : B() {
override val o = m + n
}
class D2 (m: Int, n: Int) : B() {
override val o = m * n
}
I need a "factory function" f that gives me instances of D1 or D2 by calling it as f<D1>() or f<D2>() with hard coded parameters, say 3 and 4. The following doesn't work but illustrates what I need:
// won't compile; just demonstrates what I need
fun < T : B > f () : T {
return T(3, 4) // i. e. return T.constructor(m, n)
}
How to best accomplish this? Any DRY way is fine as long I don't have to repeat 3, 4 all over my code when I instantiate D1 or D2
The only way to do it is via reflection and reified type parameter:
inline fun <reified T : B> f(m: Int = 3, n: Int = 4): T {
val constructor = T::class.constructors.first {
it.parameters.size == 2 &&
it.parameters.all { param -> param.type == Int::class }
}
return constructor.call(m, n)
}
Here's an alternate way without reflection, but you have to manually type out a line for each class you want to handle.
inline fun <reified T : B> f(): T{
val m = 3
val n = 4
return when (T::class) {
D1::class -> D1(m, n)
D2::class -> D2(m, n)
else -> error("Unsupported type ${T::class}")
} as T
}

Generic function for all number-like values?

I'd like to write a generic Kotlin function that works with arbitrary types, as long as they support some basic numeric operations, such as comparison and addition. Something like this (note: this code doesn't compile):
fun <T : ???> twiceTheLarger(a: T, b: T) = if (a > b) a + a else b + b;
In C++, this kind of code works. The following C++ twiceTheLarger function takes anything that supports the + and > operators, be it a primitive numeric type or a custom class:
#include <iostream>
template <typename T> T twiceTheLarger(T a, T b) {
return a > b ? a + a : b + b;
}
int main() {
std::cout << twiceTheLarger(1, 2) << std::endl; // int values
std::cout << twiceTheLarger(42.0, 1.0) << std::endl; // double values
}
How can I get a similar result in Kotlin? The best way I could come up so far is to explicitly pass an object with the required functions, like this:
interface NumericOperators<T> {
fun plus(a: T, b: T): T
fun greaterThan(a: T, b: T): Boolean
}
object IntNumericOperators : NumericOperators<Int> {
override fun plus(a: Int, b: Int) = a + b
override fun greaterThan(a: Int, b: Int) = a > b
}
object DoubleNumericOperators : NumericOperators<Double> {
override fun plus(a: Double, b: Double) = a + b
override fun greaterThan(a: Double, b: Double) = a > b
}
fun <T> twiceTheLarger(a: T, b: T, operators: NumericOperators<T>) =
if (operators.greaterThan(a, b)) operators.plus(a, a) else operators.plus(b, b)
fun main() {
println(twiceTheLarger(1, 2, IntNumericOperators)) // int values
println(twiceTheLarger(42.0, 1.0, DoubleNumericOperators)) // double values
}
Is there a better way?
Edit:
I realize that I could create overloads for each primitive numeric type. The thing is that I'm writing a library function that needs to work with arbitrary number-like types, even types my library doesn't know about. So type-specific overloads are not an option.
You will need to create functions for each primitive type. You can't use <T : Number>, despite all numbers in Kotlin inherit this. Number superclass is used only for the castings.
You'll need to create functions or extension functions:
fun Int.twiceTheLarger(a: Int, b: Int) = if (a > b) a + a else b + b;
fun Double.twiceTheLarger(a: Double, b: Double) = if (a > b) a + a else b + b;
It would be great if you can utilize Comparable<T> in another function for the comparison. Types of T need to overload operator fun plus(other: T) as well.
interface Addable<T>: Comparable<T>{
operator fun <T> Addable<T>.plus(a: T)
}
fun <T : Addable<T>> T.twiceTheLarger(a: T, b: T) {
return if (a > b) a.plus(a) else b + b
}

How to create an 'andThen' as an infix operator for composability on a generic class in Kotlin?

Problem Statement: I'm trying to recreate Scala/Finagle's andThen method chaining/composition across two types: Filters and Services.
The goal is to be able to do something like this:
val f1 = Filter1()
val f2 = Filter2()
val s3 = Service3()
val pipeline = f1 andThen f2 andThen s3
val result = pipeline(4) //execute pipeline with integer value of 4
Filters should be combinable with other filters and also a service to "end a chain". Services should also be combinable with other services. Both seem to lead to Unresolved reference andThen
Existing non-working solution:
typealias Transformer<A,B> = (A) -> B
abstract class Service<A,B>: Transformer<A,B> {
//DOESN'T WORK
infix fun <A,B,C> Service<A,B>.andThen(f: Service<B,C>): Service<A,C> {
val left = this
return object : Service<A, C>() {
override fun invoke(p1: A): C {
return f(left.invoke(p1))
}
}
}
}
typealias TwoWayTransformer<A,B,C,D> = (A, Service<C,D>) -> B
abstract class Filter<A,B,C,D>: TwoWayTransformer<A,B,C,D> {
//DOESN'T WORK
infix fun <A,B,E,F> Filter<A,B,C,D>.andThen(next: Filter<C,D,E,F>): Filter<A,B,E,F> {
val left = this
return object: Filter<A,B,E,F>() {
override fun invoke(a: A, service: Service<E,F>): B {
val s = object: Service<C,D>() {
override fun invoke(c: C): D { return next.invoke(c,service) }
}
return left.invoke(a,s)
}
}
}
//DOESN'T WORK
infix fun <A,B,C,D> Filter<A,B,C,D>.andThen(next: Service<C,D>): Service<A,B> {
val left = this
return object: Service<A,B>() {
override fun invoke(a: A): B {
return left.invoke(a, next)
}
}
}
}
Sidebar:
Filter<A,B,C,D> can stitch with Filter<C,D,E,F> which can stitch with Service<E,F> - the last two types of the left must match with the first two of the right when doing left andThen right.
A Filter<A,B,C,D> is simply a function of type: (A, Service<C,D>) -> E which simplifies further to (A, C->D) -> E
Link to working fiddle with example services/filters: https://pl.kotl.in/yIx80SzDF
The signatures you need are
infix fun <C> andThen(f: Service<B,C>): Service<A,C>
infix fun <E,F> andThen(next: Filter<C,D,E,F>): Filter<A,B,E,F>
infix fun andThen(next: Service<C,D>): Service<A,B>
Never add any type variables to functions that are already declared in the definition of the class. Never add an extra receiver for the class itself.

Kotlin DSL - union structure

I am designing a DSL and run into a requirement where I have a variable which could be assigned to different ways. Greatly simplified, I would like to set value property either by an integer or by an expression in String. (The real need is even more complex.)
I would like to write in my DSL:
value = 42
or
value = "6*7"
Behind the scene, the value will be stored in a DynamicValue<Int> structure which contains either an integer or the expression.
class DynamicValue<T>(dv : T?, expr : String) {
val directValue : T? = dv
val script : String? = expr
...
}
I tried several ways (delegate, class, etc), but none of them provided these syntax.
Is there a way to declare this union like structure?
What do you think about the following syntax:
value(42)
value("6*7")
//or
value+=42
value+="6*7"
You can do this with operator functions:
class DynamicValue<T>() {
var dv: T? = null
var expr: String? = null
operator fun invoke(dv : T) {
this.dv = dv
this.expr = null
}
operator fun invoke(expr: String) {
this.dv = null
this.expr = expr
}
operator fun plusAssign(dv : T) {
this.dv = dv
this.expr = null
}
operator fun plusAssign(expr: String) {
this.dv = null
this.expr = expr
}
}
You can't redefine the assign operator in Kotlin, therefor the pure syntax value=42 is not possible.
But I wouldn't go with operator functions, it's to magical. I would do this:
val value = DynamicValue<Int>()
value.simple=42
value.expr="6*7"
class DynamicValue2<T>() {
private var _dv: T? = null
private var _expr: String? = null
var simple: T?
get() = _dv
set(value) {
_dv = value
_expr = null
}
var expr: String?
get() = _expr
set(value) {
_expr = value
_dv = null
}
}
Rene's answer gave me the lead and finally I turned up with this solution.
In this solution I took all my requirements in (the ones I dropped out in my original question) so this became much more complicated than my original question would have required.
My whole requirement was to be able to add static values or scripts (snippets) running on a well guarded context. These script would be stored, and executed later. I wanted to enable the whole power of the IDE when writing the script, but would like to guard my scripts from code injections and help the user to use only the context values the script requires.
The trick I used to achieve this is to enable adding script in kotlin, but before I run the whole DSL script and create the business objects, I convert the script into a string. (This string will be executed later in a guarded, wrapped context by JSR233 engine.) This conversation forced me to tokenize the whole script before execution and search/replace some of the tokens. (The whole tokenizer and converter is rather long and boring, so I won't insert here.)
First approach
What my goal was to be able to write any of this:
myobject {
value = static { 42 } // A static solution
value = static { 6 * 7 } // Even this is possible
value = dynamic{ calc(x, y) } // A pure cotlin solution with IDE support
value = dynamic("""calc(x * x)""") // This is the form I convert the above script to
}
where calc, x and y are defined in the context class:
class SpecialScriptContext : ScriptContextBase() {
val hello = "Hello"
val x = 29
val y = 13
fun calc(x: Int, y: Int) = x + y
fun greet(name: String) = println("$hello $name!")
}
So let's see the solution! First I need a DynamicValue class to hold one of the values:
class DynamicValue<T, C : ScriptContextBase, D: ScriptContextDescriptor<C>>
private constructor(val directValue: T?, val script: String?) {
constructor(value: T?) : this(value, null)
constructor(script: String) : this(null, script)
}
This structure will ensure that exactly one of the options (static, script) will be set. (Don't bother with the C and D type parameters, they are for context-based script support.)
Then I made top level DSL functions to support syntax:
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> static(block: () -> T): DynamicValue<T, C, D>
= DynamicValue<T, C, D>(value = block.invoke())
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> dynamic(s: String): DynamicValue<T, C, D>
= DynamicValue<T, C, D>(script = s)
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> dynamic(block: C.() -> T): DynamicValue<T, C, D> {
throw IllegalStateException("Can't use this format")
}
An explanation to the third form. As I wrote before, I don't want to execute the block of the function. When the script is executed, this form is converted to the string form, so normally this function would never appear in the script when executed. The exception is a sanity warning, which would never be thrown.
Finally added the field to my business object builder:
#PlsDsl
class MyObjectBuilder {
var value: DynamicValue<Int, SpecialScriptContext, SpecialScriptContextDescriptor>? = null
}
Second approach
The previous solution worked but had some flaws: the expression was not associated with the variable it set, neither with the entity the value was set in. With my second approach I solved this problem and removed the need of equal sign and most of the unnecessary curly brackets.
What helped: extension functions, infix functions and sealed classes.
First, I split the two value types into separated classes defined a common ancestor:
sealed class Value<T, C : ScriptContextBase> {
abstract val scriptExecutor: ScriptExecutor
abstract val descriptor: ScriptContextDescriptor<C>
abstract val code: String
abstract fun get(context: C): T?
}
class StaticValue<T, C : ScriptContextBase>(override val code: String,
override val scriptExecutor: ScriptExecutor,
override val descriptor: ScriptContextDescriptor<C>,
val value: T? = null
) : Value<T, C>() {
override fun get(context: C) = value
constructor(oldValue: Value<T, C>, value: T?) : this(oldValue.code, oldValue.scriptExecutor, oldValue.descriptor, value)
}
class DynamicValue<T, C : ScriptContextBase>(override val code: String,
script: String,
override val scriptExecutor: ScriptExecutor,
override val descriptor: ScriptContextDescriptor<C>)
: Value<T, C>() {
constructor(oldValue: Value<T, C>, script: String) : this(oldValue.code, script, oldValue.scriptExecutor, oldValue.descriptor)
private val scriptCache = scriptExecutor.register(descriptor)
val source = script?.replace("\\\"\\\"\\\"", "\"\"\"")
private val compiledScript = scriptCache.register(generateUniqueId(code), source)
override fun get(context: C): T? = compiledScript.execute<T?>(context)
}
Note, that I made the primary constructor internal and created a kind of copy and alter constructor. Then I defined the new functions as extension of the common ancestor and marked them infix:
infix fun <T, C : ScriptContextBase> Value<T, C>.static(value: T?): Value<T, C> = StaticValue(this, value)
infix fun <T, C : ScriptContextBase> Value<T, C>.expr(script: String): Value<T, C> = DynamicValue(this, script)
infix fun <T, C : ScriptContextBase> Value<T, C>.dynamic(block: C.() -> T): Value<T, C> {
throw IllegalStateException("Can't use this format")
}
Using the secondary copy-and-alter constructor allows to inherit the context sensitive values. Finally I initialize the value inside the DSL builder:
#PlsDsl
class MyDslBuilder {
var value: Value<Int, SpecialScriptContext> = StaticValue("pl.value", scriptExecutor, SpecialScriptContextDescriptor)
var value2: Value<Int, SpecialScriptContext> = StaticValue("pl.value2", scriptExecutor, SpecialScriptContextDescriptor)
}
Everything is in place and now I can use it in my script:
myobject {
value static 42
value2 expr "6 * 7"
value2 dynamic { calc(x, y) }
}

How to understand a fun with = in Kotlin?

I know a standard fun just like Code 0.
The Code 1 is a sample code from webpage, I can't understand completely the
fun convertFromDomain(forecast: ForecastList) = with(forecast) {...}
Why is the symbol = added to the fun? and is the return value of the fun convertFromDomain unit ?
Code 0
fun My(forecast: ForecastList):Boolean {
...
return true;
}
Code 1
data class ForecastList(val id: Long, val city: String, val country: String, val dailyForecast: List<Forecast>) {
val size: Int
get() = dailyForecast.size
operator fun get(position: Int) = dailyForecast[position]
}
data class Forecast(val id: Long, val date: Long, val description: String, val high: Int, val low: Int,
val iconUrl: String)
fun convertFromDomain(forecast: ForecastList) = with(forecast) {
val daily = dailyForecast.map { convertDayFromDomain(id, it) }
CityForecast(id, city, country, daily)
}
Block body
Consider this function:
fun sum(a: Int, b: Int): Int {
return a + b
}
The behaviour is defined in a block body. It has an explicit return type (Int) and an explicit return statement. Both are mandatory here. If you don't specify a return type explicitely it will be Unit by default and since the inferred type of a + b is Int it won't compile.
Expression body
If you write it like this
fun sum(a: Int, b: Int) = a + b
you don't need to specify the return type because it can be inferred from the expression.You don't need a return statement either because the last expression is returned. What follows the = sign is called an expression body.
So, both functions do the same thing. The second one is only written more concise.
Note
A common mistake is to use them both at once like this:
fun sum(a: Int, b: Int) = { a + b }
What this would do becomes clear, if you specify the returned type explicitely:
fun sum(a: Int, b: Int): () -> Int = { a + b }
You would actually return a lambda of type () -> Int which is surely not what you want.
A function has usually the following form in kotlin:
fun name([parameters])[: return_type] {
// function-body
}
e.g.
fun doubleTheValue(number: Int): Int {
return number * 2
}
If your function-body is just a single-expression, you can use a shorter version of the function declaration
fun name([parameters])[: return_type] = [expression]
e.g.
fun doubleTheValue(number: Int): Int = nummber * 2
fun doubleTheValue(number: Int) = nummber * 2 // type can also be inferred
So it's nothing special, just a shorter version of a function declaration.
Traditional way to define a function is just like what you write in Code 0, which consists of function name, parameters, return type and the block body. In Kotlin, function can be defined with an expression body and the return type can be inferred from the expression body.
Suppose there is a function which convert Boolean to Int, in traditional way:
fun Boolean.toInt(): Int {
return if (this) 1 else 0
}
It can be simplified to:
fun Boolean.toInt() = if (this) 1 else 0
where the return type is inferred as Int because 1 and 0 are both Int which will be returned from the expression if (this) 1 else 0.