guidewiregosu

Converting ColumnRefs to PersistentPaths


The following query is supposed to return a list of PolicyNumbers and ReportYears along with the total number of exposures for each of the 'categories':

var query = Query.make(Exposure)
var resultSet = query.select({
    QuerySelectColumns.pathWithAlias("PolicyNumber", Paths.make(Exposure#Claim, Claim#Policy, Policy#PolicyNumber)),

    // Illegal
    QuerySelectColumns.dbFunctionWithAlias("ReportYear", DBFunction.DatePart(DatePart.YEAR, Paths.make(Exposure#Claim, Claim#ReportedDate))),

    QuerySelectColumns.dbFunctionWithAlias("ExposureCount", DBFunction.Count(Paths.make(Exposure#ID)))
})

However, the code does not compile because the signature of DBFunction.DatePart is DatePart(gw.api.database.DatePart, gw.api.database.ColumnRef), and the type of the path specifier Paths.make(Exposure#Claim, Claim#ReportedDate) is gw.api.path.PersistentPath<Exposure, Date>. Is there any way to access the Claim#ReportedDate field so that it is possible to later use it in a call to DatePart?

Judging by the fact that DBFunction.Count (but also DBFunction.Sum, DBFunction.Min, DBFunction.Max, etc.) does have a version that takes a path of type PersistentPath (see ExposureCount), I expected that it would be possible to overload DatePart using reflection, in the same way in which Count(PersistentPath<KeyableBean, Object>) is implemented in gw.api.database.GWDBFunctionEnhancement, but, unfortunately, Count(PersistentPath<KeyableBean, Object>) resolves to Count(List<IEntityPropertyInfo>). That is, it seems that – in order to provide the missing function – the class DBFunction would have to define a function of type DatePart(DatePart, List<IEntityPropertyInfo>) (or at least DatePart(DatePart, IEntityPropertyInfo), but this is also missing. Is there any way to circumvent this?


Solution

  • I think you can get almost everything you want from this query without using the DatePart dbFunction. Just return the date and the result will be aggreggated by PolicyNumber and ReportedDate. It's possible that will be close enough considering that there will be few claims for a given policyNumber. If it's necessary you can convert the result set into a typed array and do the final aggregation in Gosu code.

    Alternatively you can convert this into an entity query (where the DatePart should work) and use Gosu on the result set to print the desired columns. If this is the case consider defining a ViewEntity to include the join in a trivial way.

    You could also experiment with the "expr" DBFunction to see if you can get the results of what you're trying to do using raw SQL operations. That may allow you to combine Paths and ColumnRefs in a way that will work.

    Unfortunately the DatePart DBFunction doesn't appear to be compatible with row queries.

    Finally, this is trivial to produce from a BI solution. Can the production of this data set be removed from the ClaimCenter runtime?