I'm calling a function from the database, named some_table_generating_function
for the sake of simplicity, in order to cast the query into a select statement returning Field<Array<UUID>>
, it forces me to use the val
function of the DSL, and it creates a lot of boilerplate for doing a simple function invocation.
The following example works, but it seems to be overusing the val
function, do you have any suggestions to cleanse this piece of code?
context
.select()
.from(
select(
// fields to be selected
)
.from(
Public.SOME_TABLE_GENERATING_FUNCTION(
`val`(someString.capitalise()),
`val`(someInt),
`val`(BigDecimal(someDecimalString)),
`val`(someInt),
`val`(BigDecimal(anotherDecimalString)),
`val`(BigDecimal(yetAnotherDecimalString)),
`val`(anotherInt),
`val`(someLong),
`val`(anotherLong),
// the important bit: uuid[] parameter expected for this parameter
field(
"ARRAY({0})::uuid[]",
select(A_TABLE.UUID.cast(String::class.java))
.from(A_TABLE)
.innerJoin(ANOTHER_TABLE)
.on(A_TABLE.UUID.eq(ANOTHER_TABLE.UUID))
.where(
// additional conditions
)
) as Field<Array<UUID>>
)
)
.join(THE_TABLE)
.asTable("inner_query")
)
.where(
// additional conditions
)
CodePudding user response:
Background on the availability of convenience overloads
jOOQ's API can't overload all possible combinations of Tn
vs Field<Tn>
for larger numbers of n
where n
is the number of function parameters. For example:
- 1 parameter = 2 overloads (
f(T1)
andf(F<T1>)
- 2 parameters = 4 overloads (
f(T1, T2)
,f(T1, F<T2>)
,f(F<T1>, T2)
,f(F<T1>, F<T2>)
- 3 parameters = 8 overloads
- n parameters = 2^n overloads
While the DSL API often provides complete overloads for 2 parameters, it stops at 3 parameters, offering only 2 overloads in total:
- An overload accepting only bind values
- An overload accepting only expressions
It is the same with convenience overloads of generated user defined functions.
Possibility of a more verbose call syntax
Ordinary routines support both the convenience syntax and a more verbose call syntax:
// Convenience call
Routines.ordinaryRoutine(1, 2)
// Verbose way to call the routine, equivalent to the above
val r = OrdinaryRoutine()
r.param1 = 1
r.param2 = 2
This currently isn't available for table valued functions, which only know the "convenience syntax". Might be worth looking into generating alternatives to calling table valued functions:
Workarounds
- You could create an auxiliary function that calls your function but accepts the first set of parameters in the form of a UDT (
CREATE TYPE
), so you have to wrap the single UDT argument inDSL.val()
only a single time. This doesn't scale too well in terms of function API design, but it works around this problem - You could use plain SQL templating for the function call (
from("f(?, ?, ... {0})", someString.capitalise(), someInt, ..., field(...))
), since you're already using a plain SQL template. This won't be type safe, though. - You could extend the
JavaGenerator
to generate an extra overload for your specific case
Personally, I don't find any of these workarounds very practical. Since you probably don't have this case very often, I'd stick with the original call using explicit val
calls