Skip to main content
Jump to: navigation, search

Difference between revisions of "Equinox/p2/Query Language for p2"

< Equinox‎ | p2
(Matches operator)
Line 51: Line 51:
IQuery query = new ExpressionQuery("self ~= ANY :1", iu.getRequiredCapabilities());</pre>
IQuery query = new ExpressionQuery("self ~= ANY :1", iu.getRequiredCapabilities());</pre>
Query for the latest version of all patches:
<pre>IQuery query = new ExpressionQuery("latest self ~= :1", IInstallableUnitPatch.class));</pre>
Query for all IU's affected by a patch:
Query for all IU's affected by a patch:
<pre>IQuery query = new ExpressionQUery("self ~= ANY ALL :1", patch.getApplicabilityScope());</pre>
<pre>IQuery query = new ExpressionQUery("self ~= ANY ALL :1", patch.getApplicabilityScope());</pre>

Revision as of 04:37, 16 November 2009


p2 has a query mechanism today that makes it very hard to create an implementation that is based on a database. It is also very hard to create an efficient client/server solution. The reason for this is that most of the queries are written as java code in a callback and there is often no good way to extract the semantics of the query.

We discussed this at length on the p2 meeting on November 9. This resulted in the bugzilla Create a QueryLanguage for p2. I've spend some time on this now and today I have a fully functional IQuery implementation.


When designing the language I tried to consider two things. Who is the primary user and which are the most common queries?

Java style operators

The primary user is typically well aqquinted with Java so I opted for using java operators such as '&&' and '||' rather then SQL'ish keywords like OR and AND. I also use '.' for member access and '[' ']' to get indexed access. The latter can also be used to get keyed access.

Matches operator

A large amount of queries involve versions, version ranges, and capability matching. So managing that is important. Another thing that is important is to be able to support filtering based on ID's. All of this is now also built in to the language through the matches operator '~='. It can be though of as the 'satisfies' method on an installable unit or provided capability, as 'is included in' when used with a version and version range, as a plain matches when used with a string and a pattern, or as 'instanceof' when comparing with a class.


Some queries must make sure that the result only contains the latest version of each found IU. I added a special keyword 'latest' to make that possible.

Combined queries

It must also be possible to combine queries (hence && and ||).

Query parameters

The query must be parameterised so that expression parsing can be done once and then executed multiple times.

Java API

The expression tree created by the parser must be well documented and easy to use so that queries can be created programmatically.


Both the parser and the evaluator must be very fast. Performance must be comparable with the current solution.


Think of the query string as something that would be entered after the WHERE keyword in an SQL query, i.e.

SELECT self FROM repository WHERE ...

The query language will only cover the '...' part since the rest is implicit.

Query for all IU's that has an id:

id = :1

Query for the latest IU of some specific id:

latest id = :1

Java code to query for the latest IU that matches a specific version range (note the matches operator):

IQuery query = new ExpressionQuery("latest id = :1 && version ~= :2", id, range);

Java code to query for an IU that has a specific property set:

IQuery query = new ExpressionQuery("properties[:1] = :2", key, value);

The same query, but this time for multiple possible values:

IQuery query = new ExpressionQuery("properties[:1] = ANY :2", key, new Object[] { v1, v2, v3 });

Query for all categories found in the repository:

IQuery query = new ExpressionQuery("properties[:1] = 'true'", IInstallableUnit.PROP_TYPE_CATEGORY);

Query for all IU's that fulfil at least one of the requirements from another IU.

IQuery query = new ExpressionQuery("ANY providedCapabilities ~= ANY :1", iu.getRequiredCapabilities());
IQuery query = new ExpressionQuery("self ~= ANY :1", iu.getRequiredCapabilities());

Query for the latest version of all patches:

IQuery query = new ExpressionQuery("latest self ~= :1", IInstallableUnitPatch.class));

Query for all IU's affected by a patch:

IQuery query = new ExpressionQUery("self ~= ANY ALL :1", patch.getApplicabilityScope());

I think it would be valuable if users of p2 that have the need for specific queries could list them here. It is not unlikely that some queries might motivate some extension to the current syntax or to how the evaluator works.


p2query : ('latest' | 'distinct')? orExpression ;

orExpression : andExpression ( '||' andExpression )* ;

andExpression : notExpression ( '&&' notExpression )* ;

   : '!' notExpression
   | binaryExpression

op : '=' | '!=' | '>' | '>=' | '<' | '<=' | '~=' ;

binaryExpression : sideExpression op sideExpression ;

sideExpression : ('any' | 'all')? memberExpression ;

memberExpression : unaryExpression ( ( '.' ID ) | ( '[' memberExpression ']' ) )* ;

   : '(' orExpression ')'
   | '[' memberExpression ( ',' memberExpression )* ']' // #array construct
   | '/' regexpPattern '/'
   | INT
   | parameter
   | 'self'
   | 'null'
   | 'true'
   | 'false'
   | ID // # implies self.identifier

   : ':' INT

The expression tree model


Copyright © Eclipse Foundation, Inc. All Rights Reserved.