I am using kotlin-exposed for update/upsert query , I could see that update query return int whereas upsert returns unit, I was looking for a work around where I can find the updated resultRow if it is feasible.
the current repository layer looks something like this
suspend fun set(entity: SomeEntity)
suspend fun get(entityId: Int): SomeEntity?
here get is using EntityTable.select { }.firstOrNull() and I am able to map it back to my entity , whereas in set I have options of using upsert or update and both of them not able to return result row.
Just wanted to check if there a way I can return the updated Result row in kotlin-exposed.
Related
How can I get the last key or value in a Kotlin Map collection? It seems like it cannot be done by using an index value.
There's a couple ways it can be done. While you can't elegantly print a map directly, you may print it's entry set.
The first way, and the way that I DO NOT recommend, is by calling the .last() function on the entry set. This can be accomplished with testMap.entries.last(). The reason I don't recommend this method is because in real data this method is non-deterministic -- meaning there's no way to guarantee the characteristics of the value returned.
While I don't recommend this method, I don't know your application and this may be sufficient.
I DO recommend using the .sortedBy() function on your entry set, and then calling .last() on it. This allows you to make some sort of assumption about the results returned, something that is typically necessary, otherwise why do you want the last?
See this example comparing the two methods and then comparing the method against the order you would get if you iterate with the .forEach function:
fun main(args: Array<String>) {
val testMap = mutableMapOf<Long, String>()
testMap[1] = "Hello"
testMap[5] = "World"
testMap[3] = "Foobar"
println(testMap.entries.last())
println(testMap.entries.sortedBy { it.key }.last())
println("\norder via loop:")
testMap
.entries
.forEach {
println("\t$it")
}
}
Take a look at the output:
3=Foobar
5=World
order via loop:
1=Hello
5=World
3=Foobar
Here we see that the value returned from .last(), is the last value that was inserted into the map - the same happens with .forEach. This is okay, but usually we want our map to have some sort of order. In this example, i've called for the entry set to be sorted by the key value, so that our call to .last() on the entry set returns the key/value pair with the largest key.
I have a collection with objects that contain a value field and I need reduce information objective which one is more efficent or better and why?.
settings.filter {it.value != null }.forEach{
doSomething ....
}
settings.forEach{
if(it.value != null){
doSomething ...
}
filter allocates a list, so the second one will be faster. But if your list isn’t many hundreds of items long, the difference is negligible and you should choose what you think is more readable code. In this case I think the second one is easier to read anyway.
Here is the internal implementation of filter function used in Kotlin Collection.
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate) // New Array List Object Creation
}
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
Here you can see, it creates new list. It creates an empty arraylist and add filtered elements to new list.
Adding to Tenfour04's answer, for small list you can use filter as its more idiomatic. If you need to go with optimal way, you can use non null check.
Also you do this more idiomatically like this,
settings.filterNotNull().forEach {} //It also create extra memory.
Or you can use create your own idiomatic foreach extension function filtering null values, without creating extra space
fun <T> Iterable<T?>.forEachNonNull(a: (T) -> Unit) {
for (i in this) {
if (i != null){
a.invoke(i)
}
}
}
You can use like this.
settings.forEachNonNull {
}
As other answers mention, the first example will create a temporary list in memory. In practice, this isn't usually worth worrying about — but as you say, if the list could be very big (say, tens of thousands of items or more) then it could become significant.
However, there's a ‘best of both worlds’ option, which is to use a sequence:
settings.asSequence()
.filterNotNull()
.forEach {
// doSomething ....
}
This looks like the first example (apart from the added asSequence() and line breaks), but performs about as well as the second. That's because sequences are evaluated lazily: in this case filterNotNull() doesn't create a new list, but adds an action that will be executed as part of the forEach. You can add futher processing steps in between, too, and nothing will actually get evaluated until it's needed.
There's a bit of overhead in setting it all up (which is why sequences aren't the default), but that overhead doesn't depend on the size of the list — so if you have big lists and/or lots of processing steps, it can save a lot of memory. (It can also save a lot of processing in cases where you're not using all the results, such as when the last operation is a find().)
I am currently updating table by using:
fun <T: MyRecordInterface<*>> updateRecord(record: T) {
record.setField1("field1")
record.setField2("field2")
record.update()
}
That allow to update different types of record that share the same interface:
updateRecord(myRecord1Instance)
updateRecord(myRecord2Instance)
I would like to return the full updated record after update, so I did:
fun <T: MyRecordInterface<*>> updateRecord(record: T): T {
record.setField1("field1")
record.setField2("field2")
record.update()
record.refresh()
return record
}
Is it possible to add returning clause to the update query so that I will not have to issue 2 query in this method ?
You can turn on Settings.returnAllOnUpdatableRecord globally, which will fetch all the resulting values (identities, trigger-generated values, etc.) automatically for you on every store(), insert(), update() call.
This is applied globally, and incurs some overhead, especially if you do not want those resulting values, so it may make sense to use a new Configuration with the above Settings only where this is really needed.
I have a column title in a SQL table myTable.
Using Kotlin and JDBI, how would I go about getting all the distinct entries in this table?
This is what I have tried so far:
val jdbi = Jdbi.create("...url", "...user", "...password")
fun getTitles(): List<String> = jdbi.withHandleUnchecked { handle ->
handle.createQuery("select distinct(title) from myTable;")
.mapTo(String.javaClass)
.list()
However, this gives me the following exception:
A bean, Companion was mapped which was not instantiable (cannot find appropriate constructor)
What's going wrong here?
Apparently, String.javaClass is not what I want here (as it is a different type than is required). It is String::class.java.
Both of these interfaces define only one method
public operator fun iterator(): Iterator<T>
Documentation says Sequence is meant to be lazy. But isn't Iterable lazy too (unless backed by a Collection)?
The key difference lies in the semantics and the implementation of the stdlib extension functions for Iterable<T> and Sequence<T>.
For Sequence<T>, the extension functions perform lazily where possible, similarly to Java Streams intermediate operations. For example, Sequence<T>.map { ... } returns another Sequence<R> and does not actually process the items until a terminal operation like toList or fold is called.
Consider this code:
val seq = sequenceOf(1, 2)
val seqMapped: Sequence<Int> = seq.map { print("$it "); it * it } // intermediate
print("before sum ")
val sum = seqMapped.sum() // terminal
It prints:
before sum 1 2
Sequence<T> is intended for lazy usage and efficient pipelining when you want to reduce the work done in terminal operations as much as possible, same to Java Streams. However, laziness introduces some overhead, which is undesirable for common simple transformations of smaller collections and makes them less performant.
In general, there is no good way to determine when it is needed, so in Kotlin stdlib laziness is made explicit and extracted to the Sequence<T> interface to avoid using it on all the Iterables by default.
For Iterable<T>, on contrary, the extension functions with intermediate operation semantics work eagerly, process the items right away and return another Iterable. For example, Iterable<T>.map { ... } returns a List<R> with the mapping results in it.
The equivalent code for Iterable:
val lst = listOf(1, 2)
val lstMapped: List<Int> = lst.map { print("$it "); it * it }
print("before sum ")
val sum = lstMapped.sum()
This prints out:
1 2 before sum
As said above, Iterable<T> is non-lazy by default, and this solution shows itself well: in most cases it has good locality of reference thus taking advantage of CPU cache, prediction, prefetching etc. so that even multiple copying of a collection still works good enough and performs better in simple cases with small collections.
If you need more control over the evaluation pipeline, there is an explicit conversion to a lazy sequence with Iterable<T>.asSequence() function.
Completing hotkey's answer:
It is important to notice how Sequence and Iterable iterates throughout your elements:
Sequence example:
list.asSequence().filter { field ->
Log.d("Filter", "filter")
field.value > 0
}.map {
Log.d("Map", "Map")
}.forEach {
Log.d("Each", "Each")
}
Log result:
filter - Map - Each; filter - Map - Each
Iterable example:
list.filter { field ->
Log.d("Filter", "filter")
field.value > 0
}.map {
Log.d("Map", "Map")
}.forEach {
Log.d("Each", "Each")
}
filter - filter - Map - Map - Each - Each
Iterable is mapped to the java.lang.Iterable interface on the
JVM, and is implemented by commonly used collections, like List or
Set. The collection extension functions on these are evaluated
eagerly, which means they all immediately process all elements in
their input and return a new collection containing the result.
Here’s a simple example of using the collection functions to get the
names of the first five people in a list whose age is at least 21:
val people: List<Person> = getPeople()
val allowedEntrance = people
.filter { it.age >= 21 }
.map { it.name }
.take(5)
Target platform: JVMRunning on kotlin v. 1.3.61 First, the age check
is done for every single Person in the list, with the result put in a
brand new list. Then, the mapping to their names is done for every
Person who remained after the filter operator, ending up in yet
another new list (this is now a List<String>). Finally, there’s one
last new list created to contain the first five elements of the
previous list.
In contrast, Sequence is a new concept in Kotlin to represent a lazily
evaluated collection of values. The same collection extensions are
available for the Sequence interface, but these immediately return
Sequence instances that represent a processed state of the date, but
without actually processing any elements. To start processing, the
Sequence has to be terminated with a terminal operator, these are
basically a request to the Sequence to materialize the data it
represents in some concrete form. Examples include toList, toSet,
and sum, to mention just a few. When these are called, only the
minimum required number of elements will be processed to produce the
demanded result.
Transforming an existing collection to a Sequence is pretty
straightfoward, you just need to use the asSequence extension. As
mentioned above, you also need to add a terminal operator, otherwise
the Sequence will never do any processing (again, lazy!).
val people: List<Person> = getPeople()
val allowedEntrance = people.asSequence()
.filter { it.age >= 21 }
.map { it.name }
.take(5)
.toList()
Target platform: JVMRunning on kotlin v. 1.3.61 In this case, the
Person instances in the Sequence are each checked for their age, if
they pass, they have their name extracted, and then added to the
result list. This is repeated for each person in the original list
until there are five people found. At this point, the toList function
returns a list, and the rest of the people in the Sequence are not
processed.
There’s also something extra a Sequence is capable of: it can contain
an infinite number of items. With this in perspective, it makes sense
that operators work the way they do - an operator on an infinite
sequence could never return if it did its work eagerly.
As an example, here’s a sequence that will generate as many powers of
2 as required by its terminal operator (ignoring the fact that this
would quickly overflow):
generateSequence(1) { n -> n * 2 }
.take(20)
.forEach(::println)
You can find more here.
Iterable is good enough for most use cases, the way iteration is performed on them it works very well with caches because of the spatial locality. But the issue with them is that whole collection must pass through first intermediate operation before it moves to second and so on.
In sequence each item passes through the full pipeline before the next is handled.
This property can be determental to the performance of your code especially when iterating over large data set. so, if your terminal operation is very likely to terminate early then sequence should be preferred choice because you save by not performing unnecessary operations. for example
sequence.filter { getFilterPredicate() }
.map { getTransformation() }
.first { getSelector() }
In above case if first item satisfies the filter predicate and after map transformation meets the selection criteria then filter, map and first are invoked only once.
In case of iterable whole collection must first be filtered then mapped and then first selection starts