G'day:
A quick one today. I showed just a ColdFusion-only solution to some code in my previous article the other day: "CFML: emulating query-of-query group-by with higher-order functions". I figured when coming up with the completed code in a runnable example, I should make it work on both platforms. Here it is.
<cfscript>
function getUngroupedRecords(required numeric rows) {
createRows = (number) => repeatString(",", rows).listToArray(",", true)
date = () => now().add("d", randRange(-365, 365))
amount = () => randRange(1,10000) / 100
fakedDbData = queryNew(
"settlementDate,LongTermGainLoss,ShortTermGainLoss",
"Date,Double,Double",
createRows(rows).map((_) => [date(), amount(), amount()])
)
return fakedDbData
}
ungroupedRecords = getUngroupedRecords(20)
writeDump(ungroupedRecords)
groupedRecords = ungroupedRecords.reduce((grouped={}, row) => {
y = row.settlementDate.year()
m = row.settlementDate.month()
key = "#y#-#m#"
grouped[key] = grouped[key] ?: {stgl = 0, ltgl = 0}
grouped[key].stgl = grouped[key].stgl + row.ShortTermGainLoss
grouped[key].ltgl = grouped[key].ltgl + row.LongTermGainLoss
return grouped
}).reduce(
(records, key, values) => {
records.addRow({
month = key.listLast("-"),
year = key.listFirst("-"),
ltgl = values.ltgl,
stgl = values.stgl
})
return records
},
queryNew("month,year,ltgl,stgl", "Integer,Integer,Double,Double")
).sort((r1, r2) => {
yearDiff = r1.year - r2.year
if (yearDiff != 0) {
return yearDiff
}
return r1.month - r2.month
})
writeDump(groupedRecords)
</cfscript>
Some notes on that:
- I was using ColdFusion-only syntax for arrow functions with only one parameter: CF - correctly - does not require parentheses for the function signature here. Lucee however does, so I added them.
- As previously-mentioned, Lucee didn't like arrayNew(1).resize(number) here, so I've changed it to being a bit shit, but at least it works on Lucee.
- Lucee still doesn't return the updated query from Query.addRow, it returns the number of rows added (as per queryAddRow). ColdFusion changed this back in CF2018, so Lucee has some catch-up to do here. Anyway I needed to split this into two statements to make it work on Lucee.
- Originally I had the sort callback as one expression to demonstrate a "trick" with variable assignment expressions, but whilst this worked in Lucee, ColdFusion choked on it. The callback was: (r1, r2) => (yearDiff = r1.year - r2.year) ? yearDiff : r1.month - r2.month. This pushed well past the bounds of what is clearly understandable, and I think the long-hand version I used is better code. But it was a bug in ColdFusion that the short version didn't work.
Anyway… this version of the code works on both ColdFusion and Lucee.
Righto.
--
Adam