>From what testing I've done so far, the qualifier isn't put on for prefetch queries, which leaves me at the same situation as when using my datacontext delegate.
And I also have one case where I need to be able to disable the qualifier on a specific entity for a specific datacontext. I don't think this is possible even if the modeler qualifier was working in all other cases. I consider doing something else, like an SQL template, but I'd still have entities being fetched in this situation where foreign keys from that entity wouldn't find a matching foreign entity due to qualifier restriction. On Tue, Sep 24, 2013 at 12:07 PM, Andrus Adamchik <[email protected]> wrote: >>> I still need a way to filter all query >>> types for specific entities to filter out certain entities (appending >>> "where INVALIDATED = 'N'"). > > Is this a global rule, or does it depend on some context (like user role)? If > it's the former, you can add a qualifier to affected entities in the Modeler. > > Andrus > > On Sep 24, 2013, at 7:00 PM, Mike Kienenberger <[email protected]> wrote: > >> Here's one possible way to add support for intercepting prefetch >> queries. I'm not entirely certain it's the best way, but I didn't >> see another obvious point. >> >> What I did was to call >> QueryRouter.willPerformQuery(PrefetchSelectQuery query) before routing >> the newly-created prefetch select query. >> >> For DataDomainQueryAction, this will call context.willPerformQuery() >> if there's a non-null context. >> For anything else (DataDomainLegacyQueryAction, MockQueryRouter), it's a >> noop. >> >> If the returned query is null, then we skip routing the query and >> return either true or false. I picked true since it might be useful >> to process children of the prefetch even if the prefetch is not >> skipped. My own use case is never going to return null, so I'm fine >> with false. >> >> There's also no reason why I picked >> QueryRouter.willPerformQuery(PrefetchSelectQuery query) instead of >> QueryRouter.willPerformQuery(Query query) other than it made it more >> obvious that this method was only being used for >> PrefetchSelectQueries. But there may be other kinds of queries which >> should also be going through this method. The more I think about >> this, the more reasonable it seems have it be Query since developers >> might be writing their own Query types, and any Queries being created >> internally should be exposed through >> DataContextDelegate.willPerformQuery, and the QueryRouter is the most >> likely place to be able to forward such new queries. >> >> This has solved my issues with prefetching under 3.1. I'm still open >> to suggestions for solving my specific problem another way in the >> application code (adding database table views isn't an option), but I >> think exposing prefetch queries (as well as others) is something we >> should be supporting in Cayenne. >> >> >> Index: >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java >> =================================================================== >> --- >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java >> (revision 1524993) >> +++ >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java >> (working copy) >> @@ -27,6 +27,7 @@ >> >> import org.apache.cayenne.CayenneRuntimeException; >> import org.apache.cayenne.map.DataMap; >> +import org.apache.cayenne.query.PrefetchSelectQuery; >> import org.apache.cayenne.query.Query; >> import org.apache.cayenne.query.QueryMetadata; >> import org.apache.cayenne.query.QueryRouter; >> @@ -163,4 +164,8 @@ >> >> return q != null ? q : executedQuery; >> } >> + >> + public Query willPerformQuery(PrefetchSelectQuery prefetchQuery) { >> + return prefetchQuery; >> + } >> } >> Index: >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java >> =================================================================== >> --- >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java >> (revision 1524993) >> +++ >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java >> (working copy) >> @@ -772,4 +772,14 @@ >> } >> } >> } >> + >> + public Query willPerformQuery(PrefetchSelectQuery prefetchQuery) { >> + // Notify DataContextDelegate that we have created a new >> PrefetchSelectQuery >> + if (null != context) { >> + Query transformedQuery = >> context.nonNullDelegate().willPerformQuery(context, prefetchQuery); >> + return transformedQuery; >> + } else { >> + return prefetchQuery; >> + } >> + } >> } >> Index: >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryRouter.java >> =================================================================== >> --- >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryRouter.java >> (revision 1524993) >> +++ >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryRouter.java >> (working copy) >> @@ -49,4 +49,6 @@ >> * @throws NullPointerException if a map parameter is null. >> */ >> QueryEngine engineForDataMap(DataMap map); >> + >> + Query willPerformQuery(PrefetchSelectQuery prefetchQuery); >> } >> Index: >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java >> =================================================================== >> --- >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java >> (revision 1524993) >> +++ >> framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java >> (working copy) >> @@ -114,9 +114,15 @@ >> >> // pass prefetch subtree to enable joint prefetches... >> prefetchQuery.setPrefetchTree(node); >> - >> + >> + Query transformedQuery = router.willPerformQuery(prefetchQuery); >> + if (null == transformedQuery) { >> + // Not sure if we want to return false instead. >> Returning true seems safer. >> + return true; >> + } >> + >> // route... >> - prefetchQuery.route(router, resolver, null); >> + transformedQuery.route(router, resolver, null); >> return true; >> } >> >> Index: >> framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/MockQueryRouter.java >> =================================================================== >> --- >> framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/MockQueryRouter.java >> (revision 1524993) >> +++ >> framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/MockQueryRouter.java >> (working copy) >> @@ -50,4 +50,8 @@ >> public QueryEngine engineForDataMap(DataMap map) { >> return new MockQueryEngine(); >> } >> + >> + public Query willPerformQuery(PrefetchSelectQuery prefetchQuery) { >> + return prefetchQuery; >> + } >> } >> >> >> >> On Mon, Sep 23, 2013 at 7:04 PM, Mike Kienenberger <[email protected]> >> wrote: >>> All of my tests pass now, but I'm still hitting a few issues for 3.1 >>> that the tests didn't reveal. >>> >>> In previous versions (not sure when it changed), there existed the >>> ability to intercept prefetch queries using >>> DataContextDelegate.willPerformQuery() or willPerformGenericQuery(). >>> Those queries are no longer available -- only the original query with >>> the prefetchTree goes through those methods. >>> >>> It's the end of the day here, so I haven't traced through the code yet >>> to see what's going on, but I still need a way to filter all query >>> types for specific entities to filter out certain entities (appending >>> "where INVALIDATED = 'N'"). I've got this working for select >>> queries, relationship queries, objectIdQueries, but not prefetch >>> queries. >>> >>> And I'm still wondering what the difference between >>> willPerformGenericQuery and willPerformQuery might be. So far, I >>> just forward willPerformGenericQuery requests through my >>> willPerformQuery code. >> >
