Exposed: Aggregate functions can return null (per the spec) but not in Exposed

Created on 9 Aug 2016  路  2Comments  路  Source: JetBrains/Exposed

Aggregate SQL functions such as sum, avg, max and such return NULL if there was no rows. Has this been considered ? It seems null cannot be expressed currently and will show itself as a NPE with quite high surprise factor in the it[sumCol] call.

val sumCol = TestTable.intCol.sum()
TestTable
        .slice(sumCol)
        .selectAll()
        .map { it[sumCol] }
        .firstOrNull()

*http://www.h2database.com/html/functions.html#sum
*http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_sum

Most helpful comment

You are absolutely right about nullability of aggregated functions, but I think that not all of them can return null value (count for example).
I've fixed it and add your test to ensure.
Also I have changed return value of avg function to BigDecimal and it's possible to provide scale to it (test also included).

All 2 comments

That was quick. We are not quite there yet however. It only works because you .max() on a nullable column.

This still fails:

@Test fun testGroupBy06() {
    withCitiesAndUsers { cities, users, userData ->
        val maxNullableId: Max<Int> = cities.id.max()

        cities.slice(maxNullableId).selectAll()
                .map { it[maxNullableId] }.let { result ->
            assertTrue(result.size == 1)
            assertNotNull(result.single())
        }

        cities.slice(maxNullableId).select { cities.id.isNull() }
                .map { it[maxNullableId] }.let { result: List<Int?> ->
            assertTrue(result.size == 1)
            assertNull(result.single())
        }
    }
}

I would think all of the aggregate functions should return a nullable version of their types.

Also, about the Average function there seems to be a need for changing the type.
H2 docs says: "The returned value is of the same data type as the parameter."
PostgreSQL: "numeric for any integer-type argument, double precision for a floating-point argument, otherwise the same as the argument data type"
MySQL: "The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE)."

Im not sure if what the intersection with these statements is.. but at the very least is there a way of converting from an Int column to a Double column?

You are absolutely right about nullability of aggregated functions, but I think that not all of them can return null value (count for example).
I've fixed it and add your test to ensure.
Also I have changed return value of avg function to BigDecimal and it's possible to provide scale to it (test also included).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

barry-m picture barry-m  路  3Comments

yuri-li picture yuri-li  路  3Comments

gertvdijk picture gertvdijk  路  4Comments

mgmeiner picture mgmeiner  路  3Comments

kszymanski85 picture kszymanski85  路  4Comments