Hi Gordon,
There are essentially two extension points where you can
transform/simplify your queries. One is to manipulate the QueryModels
after they have been created by re-linq, one is to transform the
expression tree before (or while) they are parsed by re-linq.
Manipulating QueryModels is easy, you just do this in your executor
after you get them from the QueryParser.
Manipulating the expression tree can, e.g., be done by decorating
(wrapping) the QueryParser and running a visitor over the expression
in GetParsedQuery before the inner QueryParser is called.
Whether you want to manipulate query models or expression trees
depends on how much metadata you need. In the Query Model form,
re-linq has already identified sub-queries, associated query source
references with the actual sources, and structured the query in
from/where/orderby/select and result transformations. In the
expression form, it's still the complex AST given by the compiler. In
general, I'd suggest working on the QueryModel unless important
information has already been removed or the expression transformation
is extremely local (the typical ExpressionTransformer use case).
In our own re-linq backend, the SQL generator, we have a third option.
Since we translate the QueryModels to yet another model, the
SqlStatementModel, we can perform simplifications while we're doing
this translation resp. on the SqlStatementModel itself. In fact, this
is the option I usually chose in there rather than changing the
QueryModel.
For more specific ideas about your scenario, it would probably be good
to know what simplification exactly you would want to perform. I.e.,
given a query/Query Model; how would you want it to look after your
simplification?
This is probably more or less the query model from your gist (call
ToString on the QM to get a string representation, then add line
breaks and indentation):
(from m in (
from d in q
select new
{
matches = ( from i in [d].run1 select new { pt = [i] } ) // QM 3
}
) // QM 2
from j in [m].matches
select [j].pt
=> Sum
) // QM 1
re-linq might simplify this a little bit more, I'm not sure if QM 2 is
inlined. But let's pretend it isn't for the sake of the argument ;)
Feeding this into your elimination algorithm, what would you like it to become?
Best regards,
Fabian