> 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.

This is bad and is not supposed to happen. Appears to be a bug. I am checking 
SelectQueryPrefetchRouterAction, and it applies *root* entity qualifier to 
prefetch query instead of prefetched entity. Should be a relatively easy fix 
for "disjoint" prefetches at least. 

> What do you think of my general idea of exposing PrefetchSelectQueries to the 
> DataContextDelegate?

FWIW, I was hoping DataContextDelegate itself is on the way out.

So I'd start with entity qualifier, as it is intended exactly for what you are 
trying to do - filtering selects (presuming we fix the bug above). The "special 
DataContext" case where the qualifier should be ignored can probably be handled 
by starting a separate ServerRuntime, where you can strip off the qualifiers. 
For whatever overhead it creates (ideally not much), this has an advantage of 
cleanly separating "spaces" with different ORM rules. 

Andrus


On Sep 24, 2013, at 8:03 PM, Mike Kienenberger <[email protected]> wrote:
> 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.
>>> 
>> 
> 

Reply via email to