QueryFragment
A piece of SQL and the parameters it names, kept together so that neither can be dropped on the way.
The point of it is a WHERE assembled at runtime. Written as plain strings, a filter that is sometimes there and sometimes not means keeping a condition list and a parameter map in step by hand, and the failure when they drift is a parameter the query names and nobody supplied. Here the two travel together and join keeps them together.
val filter = listOfNotNull(
name?.let { "cognomen ILIKE @name" withParam ("name" to "%$it%") },
minRank?.let { "rank_order >= @minRank" withParam ("minRank" to it) },
province?.let { "home_province = @province" withParam ("province" to it) }
).join(" AND ")
val senators = db.select("*").from("senate")
.where(filter.sql)
.fetchObjects<Senator>(filter.params)Content copied to clipboard
The two halves are handed over separately and on purpose. A builder never carries parameters - that is what lets RunnableQuery.toSql be embedded in a larger statement without leaving values behind - so filter.sql goes to the clause and filter.params to the terminal. Writing both is what keeps the pair visible.