Hi, devs. I would like to propose new QueryManager which will deprecate our store.search(* methods This proposal is based on Vincent ideas at http://markmail.org/message/mjgg52coupsmfomg and QueryManager from JCR v2 QueryManager is designed for low-level querying in Java code. (QueryPlugin for high-level and velocity) The main idea is support of multiple languages and easy to add new languages. This is needed for JCRStore. Here is interfaces: public interface QueryManager { Query createQuery(String statement, String language); Query getNamedQuery(String qname); String[] getLanguages(); boolean hasLanguage(String language); } public interface Query { enum Language { HQL, XPATH, JCRSQL } <T> List<T> execute(); Query bindValue(String var, Object val); Query setLimit(int limit); Query setOffset(int offset); } Here is abstract usecase: QueryManager qm = xwiki.getStore().getQueryManager(); Query q = qm.getNamedQuery("SomeNameOfQuery"); if (q==null && qm.hasLanguage(Query.Language.HQL.name())) { q = qm.createQuery("from XWikiDocument where author=:var", Language.HQL.name()); } else if (q==null && qm.hasLanguage(Language.XPATH.name())) { q = qm.createQuery("/*/*[@author=:var]", Language.XPATH.name()); } else throw new RuntimeException(); List<XWikiDocument> res = q.setLimit(10).setOffset(10) .bindValue("var", "Some.Author").execute(); notes: I'm not sure we need getNamedQuery right now. But it can be useful for move some complicated queries to store level (to some QueryHolders) or overriding queries. Queries are detached from store session. So session isn't opened until Query#execute(). WDYT? -- Artem Melentyev
Hi Artem, My take: 1) This looks good 2) Only use the methods that you need now and add methods as they are needed in the future. For ex if there's no need right now for named queries we should probably not use it (Of course we should think about all use cases so that we have a solution should they arise). 3) Why do we still need a QueryPlugin? I don't think it's needed anymore with the QueryManager. For me the Query Plugin should be modified to be one of the Query implementation (HQL, XPath - this one -, JCRSQL, etc). 4) I'd really like that we try to remove any velocity-specific API so that we have only 1 Java API for all. Maybe we can introduce some velocity tools to handle the cases where you think it is required. What would be those cases? 5) Why do we need to write Language.HQL.name() and not Language.HQL? Thanks -Vincent On May 25, 2008, at 5:08 PM, Artem Melentyev wrote:
Hi, devs.
I would like to propose new QueryManager which will deprecate our store.search(* methods This proposal is based on Vincent ideas at http://markmail.org/message/mjgg52coupsmfomg and QueryManager from JCR v2 QueryManager is designed for low-level querying in Java code. (QueryPlugin for high-level and velocity) The main idea is support of multiple languages and easy to add new languages. This is needed for JCRStore.
Here is interfaces:
public interface QueryManager { Query createQuery(String statement, String language); Query getNamedQuery(String qname); String[] getLanguages(); boolean hasLanguage(String language); }
public interface Query { enum Language { HQL, XPATH, JCRSQL } <T> List<T> execute(); Query bindValue(String var, Object val); Query setLimit(int limit); Query setOffset(int offset); }
Here is abstract usecase:
QueryManager qm = xwiki.getStore().getQueryManager(); Query q = qm.getNamedQuery("SomeNameOfQuery"); if (q==null && qm.hasLanguage(Query.Language.HQL.name())) { q = qm.createQuery("from XWikiDocument where author=:var", Language.HQL.name()); } else if (q==null && qm.hasLanguage(Language.XPATH.name())) { q = qm.createQuery("/*/*[@author=:var]", Language.XPATH.name()); } else throw new RuntimeException(); List<XWikiDocument> res = q.setLimit(10).setOffset(10) .bindValue("var", "Some.Author").execute();
notes: I'm not sure we need getNamedQuery right now. But it can be useful for move some complicated queries to store level (to some QueryHolders) or overriding queries. Queries are detached from store session. So session isn't opened until Query#execute().
WDYT?
-- Artem Melentyev _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
Hi, Vincent. Vincent Massol wrote:
2) Only use the methods that you need now and add methods as they are needed in the future. For ex if there's no need right now for named queries we should probably not use it (Of course we should think about all use cases so that we have a solution should they arise). Ok
3) Why do we still need a QueryPlugin? I don't think it's needed anymore with the QueryManager. For me the Query Plugin should be modified to be one of the Query implementation (HQL, XPath - this one -, JCRSQL, etc).
We need also some secure query (ex: QueryPlugin's xpath for Hibernate is secure, so it checks "query" right if query contains some non public fields), but yes, it can be some language in QueryManager.
4) I'd really like that we try to remove any velocity-specific API so that we have only 1 Java API for all. Maybe we can introduce some velocity tools to handle the cases where you think it is required. What would be those cases?
Main issue are check rights for returned documents and shorter API (ex: QueryManager#xpath(""), Query#setParams(List)). We can expose QueryManager as the QueryPlugin (ex: xwiki.getQuery() returns QueryManager, without plugin api), add some shorter methods and protect #createQuery by our @Programming annotation. WDYT?
5) Why do we need to write Language.HQL.name() and not Language.HQL?
Because "Language" is Java5 enum, but QueryManager#createQuery require String (for adding new Languages without modify the Language enum). Ok. This is not good, so I propose to: public interface Query { static final String HQL = "hql"; static final String XPATH = "xpath"; ... } And use qm.createQuery("...", Query.HQL); As well as in the JCR. (JCR don't use enums because targets at Java1.4) -- Artem Melentyev
On May 25, 2008, at 8:18 PM, Artem Melentyev wrote:
Hi, Vincent.
Vincent Massol wrote:
2) Only use the methods that you need now and add methods as they are needed in the future. For ex if there's no need right now for named queries we should probably not use it (Of course we should think about all use cases so that we have a solution should they arise). Ok
3) Why do we still need a QueryPlugin? I don't think it's needed anymore with the QueryManager. For me the Query Plugin should be modified to be one of the Query implementation (HQL, XPath - this one -, JCRSQL, etc).
We need also some secure query (ex: QueryPlugin's xpath for Hibernate is secure, so it checks "query" right if query contains some non public fields), but yes, it can be some language in QueryManager.
see below.
4) I'd really like that we try to remove any velocity-specific API so that we have only 1 Java API for all. Maybe we can introduce some velocity tools to handle the cases where you think it is required. What would be those cases?
Main issue are check rights for returned documents
We should probably have 2 Java APIs: one with restricted rights and one with unrestricted rights. Some of our org.xwiki components will be able to call the unrestricted rights api (we need to define how that will work - security policy?). But this is not related to Velocity. For example if, as a user, I write a new component I should only be able to call the restricted rights API, unless I have some extra rights set up or unless I modify the "container security policy".
and shorter API (ex: QueryManager#xpath(""), Query#setParams(List)).
We can expose QueryManager as the QueryPlugin (ex: xwiki.getQuery() returns QueryManager, without plugin api), add some shorter methods and protect #createQuery by our @Programming annotation.
I'd prefer that we don't add "shorter" methods (whatever that means - I'm still unsure) but that we have pure Java API as if the API was only called from Java. However, in order to make it simpler from Velocity we could do 2 things: * Offer some velocity tools for easier access. * Possibility create some @velocity annotations or something that would generate some velocity-based api in some cases where we could not find a good way of doing it. However I'd like to start reviewing the cases one by one to see if they can really not be called easily- enough from Velocity.
WDYT?
5) Why do we need to write Language.HQL.name() and not Language.HQL?
Because "Language" is Java5 enum, but QueryManager#createQuery require String (for adding new Languages without modify the Language enum). Ok. This is not good, so I propose to:
public interface Query { static final String HQL = "hql"; static final String XPATH = "xpath"; ... }
btw you don't need static final in an interface ;) Actually I wouldn't do it like this. Since we're now using components I would create a Query interface and create each implementation as a component. That component will be registered with a <role-hint> of "hql", "xpath", etc. Thanks -Vincent
And use qm.createQuery("...", Query.HQL); As well as in the JCR. (JCR don't use enums because targets at Java1.4)
On May 25, 2008, at 9:12 PM, Vincent Massol wrote: [snip]
5) Why do we need to write Language.HQL.name() and not Language.HQL?
Because "Language" is Java5 enum, but QueryManager#createQuery require String (for adding new Languages without modify the Language enum). Ok. This is not good, so I propose to:
public interface Query { static final String HQL = "hql"; static final String XPATH = "xpath"; ... }
btw you don't need static final in an interface ;)
Actually I wouldn't do it like this. Since we're now using components I would create a Query interface and create each implementation as a component. That component will be registered with a <role-hint> of "hql", "xpath", etc.
Actually this is orthogonal. For the component lookup we simply need a string which can come from an enum or from a static final String. I'm fine with the String. Still we should implement the Queries as components. Thanks -Vincent
Hi, Vincent. Vincent Massol wrote:
4) I'd really like that we try to remove any velocity-specific API so that we have only 1 Java API for all. Maybe we can introduce some velocity tools to handle the cases where you think it is required. What would be those cases? Main issue are check rights for returned documents
We should probably have 2 Java APIs: one with restricted rights and one with unrestricted rights. Some of our org.xwiki components will be able to call the unrestricted rights api (we need to define how that will work - security policy?). But this is not related to Velocity. For example if, as a user, I write a new component I should only be able to call the restricted rights API, unless I have some extra rights set up or unless I modify the "container security policy".
We can create 2 QueryManagers: one with only secure languages, and another with all languages.
and shorter API (ex: QueryManager#xpath(""), Query#setParams(List)).
We can expose QueryManager as the QueryPlugin (ex: xwiki.getQuery() returns QueryManager, without plugin api), add some shorter methods and protect #createQuery by our @Programming annotation.
I'd prefer that we don't add "shorter" methods (whatever that means - I'm still unsure) but that we have pure Java API as if the API was only called from Java.
However, in order to make it simpler from Velocity we could do 2 things: * Offer some velocity tools for easier access. * Possibility create some @velocity annotations or something that would generate some velocity-based api in some cases where we could not find a good way of doing it. However I'd like to start reviewing the cases one by one to see if they can really not be called easily- enough from Velocity.
Ok. We need QueryManager for Java at first.
public interface Query { static final String HQL = "hql"; static final String XPATH = "xpath"; ... }
btw you don't need static final in an interface ;)
Actually I wouldn't do it like this. Since we're now using components I would create a Query interface and create each implementation as a component. That component will be registered with a <role-hint> of "hql", "xpath", etc.
This sounds fine. Thanks for idea. But this is implementation specific. We need QueryManager#createQuery in any case. -- Artem Melentyev
On May 28, 2008, at 2:31 PM, Artem Melentyev wrote:
Hi, Vincent.
Vincent Massol wrote:
4) I'd really like that we try to remove any velocity-specific API so that we have only 1 Java API for all. Maybe we can introduce some velocity tools to handle the cases where you think it is required. What would be those cases? Main issue are check rights for returned documents
We should probably have 2 Java APIs: one with restricted rights and one with unrestricted rights.
Actually what we have started with Sergiu is to use a @permission annotation (I'm not sure of its exact name) so that we can flag an API as requiring a specific permission. For example: @permission("admin") @permission("programming") @permission("edit") However the mechanism to "trust" some components so that they can access some privileged API is different and I think that one could be done using the JVM security policy mechanism.
Some of our org.xwiki components will be able to call the unrestricted rights api (we need to define how that will work - security policy?). But this is not related to Velocity. For example if, as a user, I write a new component I should only be able to call the restricted rights API, unless I have some extra rights set up or unless I modify the "container security policy".
We can create 2 QueryManagers: one with only secure languages, and another with all languages.
Well, this is not related to the query manager but to all our APIs in general so I'm not sure why we would create 2 query managers. [snip] Thanks -Vincent
participants (2)
-
Artem Melentyev -
Vincent Massol