[hibernate-dev] Continue "parameter list" support?
Christian Beikov
christian.beikov at gmail.com
Sat Sep 10 08:31:05 EDT 2016
May I ask how the semantics of a query could change in case of parameter
expansion in different places than IN predicate?
Since such collection valued parameters only make sense on some sort of
varg-args accepting thingy like IN or a SQLFunction, I don't really see
how this is an issue.
You could have 2 caches e.g.
* SQMCache<HQL, SQMQuery>
* SQLCache<SQMQuery, Cache<ParameterMetadata, SQLString>>
Can you please elaborate what you think is problematic about something
like that?
Am 09.09.2016 um 23:39 schrieb Steve Ebersole:
> Although, thinking about it some more, SQM itself already exposes some
> of the things QueryPlan does today. So maybe this is not such a big
> issue.
>
> I personally am just not a fan of not understanding the semantic of a
> query up front. Good translation in part comes down to good design of
> the language so that as much semantic as possible is available
> statically (from the Query itself, and from Session/SessionFactory).
>
>
> On Fri, Sep 9, 2016 at 4:35 PM Steve Ebersole <steve at hibernate.org
> <mailto:steve at hibernate.org>> wrote:
>
> Not any particular reason, HHH-10502 or otherwise. Its more a
> general question as I am integrating SQM and the new query
> translators upstream.
>
> Again, I think y'all are missing the point. The concern is not
> whether a query is cacheable or not. The concern is *when* I know
> whether it is cacheable.
>
> Consider some psuedo-code. First, the ideal case:
>
> SessionImpl#createQuery(...) {
> ...
>
> // interpret the query into SQM
> SqmStatementSelect sqm = SemanticQueryInterpreter.interpret(...);
>
> QueryPlan queryPlan;
> if ( isCacheable( sqm ) ) {
> queryPlan = queryPlanCache.get( ... );
> if ( queryPlan == null ) {
> queryPlan = new QueryPlan( ... );
> queryPlanCache.put( ..., queryPlan );
> }
> }
> else {
> queryPlan = new QueryPlan( ... );
> }
>
> return new QueryImpl( sqm, queryPlan, this );
> }
>
> versus:
>
> SessionImpl#createQuery(...) {
> ...
>
> // interpret the query into SQM
> SqmStatementSelect sqm = SemanticQueryInterpreter.interpret(...);
>
> // now we have to delay creation of the QueryPlan until later
> // because we do not know if the query is cacheable, because
> // we do not know yet whether it contains any multi-valued
> // parameters.
>
> return new QueryImpl( sqm, this );
> }
>
>
>
> On Fri, Sep 9, 2016 at 4:17 PM Christian Beikov
> <christian.beikov at gmail.com <mailto:christian.beikov at gmail.com>>
> wrote:
>
> Ah ok, I thought you wanted to drop parameter lists in general ^^
> I suppose you are discussing this because of
> https://hibernate.atlassian.net/browse/HHH-10502?
>
> I personally don't have a use case for a general parameter list
> expansion like the reporter of that issue and I also don't
> think that
> people are directly writing that kind of stuff into a query, but a
> wrapper does. All in all, I think people will be able to
> workaround if
> you remove the parameter list expansion for other places. Is
> this such a
> problem to keep around that feature?
>
> Would be interesting to see how other people make use of that
> feature.
> If everyone uses such collection valued parameters at least
> for an IN
> predicate and maybe additionally for something else like that
> FIELD
> function, you would have to wait for the parameter list anyway.
>
> Query caching can generally be handled if you introduce a
> configuration
> parameter for a fixed expansion size, but that would probably
> be even
> more work because then you would have to exectue the query
> multiple times.
>
> I just don't think that removing this feature will bring any
> benefits.
>
> Regards,
> Christian
>
> Am 09.09.2016 um 22:30 schrieb Steve Ebersole:
> > BTW, JPA really requires that we support accepting
> multi-valued bindings
> > for parameters through #setParameter. Yet another reason to
> do away with
> > #setParameterList.
> >
> >
> > On Fri, Sep 9, 2016 at 3:26 PM Steve Ebersole
> <steve at hibernate.org <mailto:steve at hibernate.org>> wrote:
> >
> >> WRT the "collection_valued_input_parameter" bit, that is
> limited in the
> >> spec to IN clauses. And more specifically in fact the spec
> specifically
> >> limits this in *exactly* the way I suggested :)
> >>
> >> <quote>
> >> in_expression ::=
> >> {state_valued_path_expression |
> type_discriminator} [ NOT ] IN
> >> { ( in_item { , in_item}* ) | ( subquery ) |
> >> collection_valued_input_parameter }
> >>
> >> in_item ::= literal | single_valued_input_parameter
> >> </quote>
> >>
> >> (see "4.6.9 In Expressions" or "4.14 BNF")
> >>
> >> In other words, the "values" of an IN expression may be
> *one of* the
> >> following:
> >>
> >> 1. an explicit list of "in-items", which in turn are
> specifically
> >> single values
> >> 2. a subquery
> >> 3. a *single* multivalued param (one placeholder to
> rule them all)
> >>
> >>
> >> As I said in my original email:
> >>
> >> <quote>
> >> we could simply assume that a IN predicate with a single
> parameter
> >> placeholder is going to be a multivalued parameter
> >> </quote>
> >>
> >> That's what JPA supports for multi-valued parameters.
> Hibernate has long
> >> supported a broader definition of
> "collection_valued_input_parameter". I
> >> am simply suggesting that we align with the limitation JPA
> already has in
> >> place.
> >>
> >> Really, the only thing I am really asking about is the
> overloaded forms of
> >> Query#setParameterList. We have to support multi-valued
> parameters *in
> >> this very limited* case. Sure. The problem with our existing
> >> broader/open-ended multi-valued param support is that we do
> not know that a
> >> parameter is multi-valued *from the query* itself.
> Specifically we have
> >> to wait and see if #setParameter or #setParameterList is
> called, on any of
> >> the parameters.
> >>
> >> Again, the "win" is that we could then know *up front* that
> a query is not
> >> cacheable (precompile-able), whereas today we have to wait
> until just
> >> before the execution (so that #setParameter and
> #setParameterList have all
> >> been called).
> >>
> >>
> >> @Vlad It depends what "query cannot be precompiled" *means*
> which is of
> >> course open to interpretation. Heck what compilation of a
> query means at
> >> all is outside the scope of the spec. Any "compilation" of
> the query that
> >> resolves to SQL of course has to wait. But "compilation"
> to a semantic
> >> form (aka, SQM) does not need to wait. In fact the SQM is
> the exact place
> >> you'd look to know whether the query (plan) is cacheable.
> >>
> >>
> >>
> >> On Fri, Sep 9, 2016 at 8:20 AM Vlad Mihalcea
> <mihalcea.vlad at gmail.com <mailto:mihalcea.vlad at gmail.com>>
> >> wrote:
> >>
> >>> Hi,
> >>>
> >>> I don't think we should deprecate such a feature.
> >>>
> >>> First, the JPA specs says the follows:
> >>>
> >>> "All input parameters must be single-valued, except in IN
> expressions
> >>> (see section 4.6.9), which support
> >>> the use of collection-valued input parameters."
> >>>
> >>> So, we kinda need to support it one way or another.
> >>>
> >>> Also, the JPA specs says that:
> >>>
> >>> "Note that use of a collection-valued input parameter will
> mean that a
> >>> static query cannot be precompiled."
> >>>
> >>> So, it's expected to have such a behavior.
> >>>
> >>> I don't think that multi-load support can replace
> paremeterList since the
> >>> former cannot use any property from a given entity.
> >>> Also, the IN predicate with parameter list applies to DTO
> projections or
> >>> native queries, so it's useful to have it.
> >>>
> >>> Vlad
> >>>
> >>> On Fri, Sep 9, 2016 at 4:03 PM, andrea boriero
> <andrea at hibernate.org <mailto:andrea at hibernate.org>>
> >>> wrote:
> >>>
> >>>> I am also not able to figure out another use case than
> the IN predicate
> >>>> so
> >>>> I am for always considering IN predicates as multi-valued.
> >>>>
> >>>> On 9 September 2016 at 14:20, Steve Ebersole
> <steve at hibernate.org <mailto:steve at hibernate.org>>
> >>>> wrote:
> >>>>
> >>>>> To be clear, this is the feature that lets you define a
> query like:
> >>>>>
> >>>>> select ... from Person p where p.name <http://p.name> in
> (:names)
> >>>>>
> >>>>> And then bind varied multiple values into that single
> parameter holder:
> >>>>>
> >>>>> query.setParameterList( "names", new String[] { "Larry",
> "Curly",
> >>>> "Moe" }
> >>>>> );
> >>>>> query.setParameterList( "names", new String[] { "John",
> "Jane" } );
> >>>>>
> >>>>> Which magically transforms to the following (rough) SQL:
> >>>>>
> >>>>> select ... from PERSON p where p.name <http://p.name> in
> (?, ?, ?)
> >>>>> select ... from PERSON p where p.name <http://p.name> in
> (?, ?)
> >>>>>
> >>>>> Effectively parameter lists allow expansion of the HQL
> statement - they
> >>>>> literally are handled by altering the HQL on the fly as
> we prepare to
> >>>>> execute the query. What that means is that we can
> really not cache
> >>>> these
> >>>>> queries, at least not until the parameters are bound
> (which kind of
> >>>> defeats
> >>>>> the purpose).
> >>>>>
> >>>>> I'd like to discuss dropping support for parameter
> lists. There are
> >>>> quite
> >>>>> a few reasons I would like to drop this support:
> >>>>>
> >>>>> 1. This is the main culprit that leads to the
> ever-resurrecting
> >>>>> discussion about DB limits on IN clauses. The one
> valid use case I
> >>>> saw
> >>>>> for
> >>>>> that lead me to add multi-load support in 5.1.
> >>>>> 2. In terms of a QueryPlan cache, this support means
> we can never
> >>>>> effectively cache the plans for these queries
> because the SQL is
> >>>>> different
> >>>>> every time we execute the query. The problem though
> is that we do
> >>>> not
> >>>>> know
> >>>>> this until well after the point that we'd resolve
> the QueryPlan.
> >>>>> chicken-egg.
> >>>>> 3. This is more an internal detail, but handling the
> parameter
> >>>> bindings
> >>>>> for these differently gets quite complicated.
> >>>>> 4. An additional internal detail is that re-writing
> the HQL on the
> >>>> fly
> >>>>> is problematic. And some of that leaks to the user
> in terms of
> >>>> result
> >>>>> caching and stats (which HQL do we use?).
> >>>>>
> >>>>> I get that this can be a useful feature for apps that
> dynamically build
> >>>>> HQL, although really for dynamic query building I think
> a criteria
> >>>> approach
> >>>>> is more appropriate. It is not so much supporting this
> feature that
> >>>> bugs
> >>>>> me, it's how we expose it. So an alternative to
> dropping this support
> >>>>> would be to support it in a different way. The main
> issue is that I
> >>>> would
> >>>>> like to *syntactically* understanding that a parameter
> placeholder
> >>>> will be
> >>>>> used for multi-valued parameter from the query itself.
> This is a
> >>>>> beyond-JPA feature, so we definitely have some leeway
> here to define
> >>>> this
> >>>>> however we want.
> >>>>>
> >>>>> I am open to suggestions as to the best syntax to
> declare that.
> >>>>>
> >>>>> An alternative would be to make some assumptions.
> Specifically, the
> >>>> only
> >>>>> time I can think this is used is inside an IN
> predicate. Am I missing
> >>>>> others? If that is the case, we could simply assume
> that a IN
> >>>> predicate
> >>>>> with a single parameter placeholder is going to be a
> multivalued
> >>>>> parameter. That assumption holds valid even if just a
> single value is
> >>>>> bound. The main win there is that we can get rid of the
> >>>>> Query#setParameterList
> >>>>> variants. setParameterList was only ever needed so that
> we could
> >>>>> understand that the parameter is multivalued - here we'd
> assume that
> >>>> from
> >>>>> its context as the IN predicate value.
> >>>>>
> >>>>> Continuing to support parameters-lists in any form does
> not really
> >>>>> address point
> >>>>> (1) above; but that's ok - the user really could , But
> each of the
> >>>>> alternatives does help with the other problems currently
> stemming from
> >>>>> parameter-list support.
> >>>>> _______________________________________________
> >>>>> hibernate-dev mailing list
> >>>>> hibernate-dev at lists.jboss.org
> <mailto:hibernate-dev at lists.jboss.org>
> >>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >>>>>
> >>>> _______________________________________________
> >>>> hibernate-dev mailing list
> >>>> hibernate-dev at lists.jboss.org
> <mailto:hibernate-dev at lists.jboss.org>
> >>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >>>>
> >>>
> > _______________________________________________
> > hibernate-dev mailing list
> > hibernate-dev at lists.jboss.org
> <mailto:hibernate-dev at lists.jboss.org>
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
> <mailto:hibernate-dev at lists.jboss.org>
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
More information about the hibernate-dev
mailing list