I have a `case` in a select over which komapper bl...
# komapper
s
I have a
case
in a select over which komapper blows up with
Copy code
java.lang.UnsupportedOperationException: null
	at org.komapper.core.dsl.expression.LiteralExpression.getColumnName(LiteralExpression.kt:14) ~[komapper-core-1.16.0.jar:na]
because I'm returning more than 3 columns in the query so it's switching to a
Record
return type instead of a tuple. How can I set an
as <name>
alias to an expression in a select? Or is there a more idiomatic solution?
full query for reference:
Copy code
val o = Meta.order

  val query = QueryDsl
    .from(o)
    .where {
      o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
      or { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") }
    }
    .select(
      o.id,
      o.clientId,
      o.revenue,
      case(
        When(
          { o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
          },
          literal("current"),
        ),
        When(
          { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") },
                        
         literal("previous"),
        )
      ).alias("period")
)
so I found
alias()
but the error is still there...
umm so, I might be getting this wrong but from what I understand it seems that
AliasExpression
doesn't use the provided column name to resolve
columnName
, but rather delegate to the original expression:
Copy code
internal data class AliasExpression<T : Any, S : Any>(
    val expression: ColumnExpression<T, S>,
    val alias: String,
    val alwaysQuoteAlias: Boolean,
) : ColumnExpression<T, S> by expression
Not sure if this is intended, from my limited point of view it doesn't seem to make too much sense?
it's also not fixable locally because I cannot implement
ColumnExpression
🫤
d
Maybe try saving the case in a val and use it both in the query and in the record?
s
@dave08 I'm not following, how would I use it in the record?
btw, was investigating a bit further and it seems a problem related to `println`ing the results
t
Try the following code:
Copy code
val period = case(
    When(
        {
            o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
        },
        literal("current"),
    ),
    When(
        { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") },

        literal("previous"),
    )
)

val query = QueryDsl
    .from(o)
    .where {
        o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
        or { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") }
    }
    .select(
        o.id,
        o.clientId,
        o.revenue,
        period
    )

val list = db.runQuery(query)

list.forEach { record ->
    println(record[o.id])
    println(record[o.clientId])
    println(record[o.revenue])
    println(record[period])
}
☝🏼 1
Another solution is to use
@KomapperProjection
to map to a class. First, create a class as follows:
Copy code
@KomapperEntity
@KomapperProjection
data class OrderDto(
    @KomapperId
    val id: Int,
    val clientId: String,
    val revenue: Int,
    val period: String,
)
Then, you can write your query as follows:
Copy code
val query = QueryDsl
    .from(o)
    .where {
        o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
        or { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") }
    }
    .selectAsOrderDto(
        id = o.id,
        clientId = o.clientId,
        revenue = o.revenue,
        period = case(
            When(
                {
                    o.date between LocalDate.parse("2023-01-01")..LocalDate.parse("2023-12-15")
                },
                literal("current"),
            ),
            When(
                { o.date between LocalDate.parse("2022-01-01")..LocalDate.parse("2022-12-15") },

                literal("previous"),
            )
        )
    )

val list: List<OrderDto> = db.runQuery(query)

list.forEach { orderDto ->
    println(orderDto.id)
    println(orderDto.clientId)
    println(orderDto.revenue)
    println(orderDto.date)
}
s
thanks @Toshihiro Nakamura that seems to do the trick for now