cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Kienenberger <mkien...@gmail.com>
Subject Re: No willPerform(Generic)Query support for prefetching queries in 3.1?
Date Tue, 24 Sep 2013 20:16:25 GMT
Added as Issue CAY-1875 - PrefetchSelectQuery incorrectly applies
entity qualifiers

On Tue, Sep 24, 2013 at 1:48 PM, Andrus Adamchik <andrus@objectstyle.org> 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.
>
> 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 <mkienenb@gmail.com> 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
>> <andrus@objectstyle.org> 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 <mkienenb@gmail.com> 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 <mkienenb@gmail.com>
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.
>>>>
>>>
>>
>

Mime
View raw message