WBEM clients use the execQuery method in the CIMClient class to search for instances that match a set of search criteria. The CIM Object Manager handles client queries for CIM data stored in the CIM Object Manager Repository and it passes to providers queries for CIM data that is served by a particular provider.
All instance providers must imlement the execQuery interface in the com.sun.wbem.provider20 package to handle client queries for the dynamic data they provide. Providers can use the classes and methods in the com.sun.wbem.query package to filter WBEM Query Language (WQL) query strings. Providers with access to an entity that handles indexing can pass the query string to that entity for parsing.
The classes and methods in the com.sun.wbem.query package represent a WBEM Query Language parser and the WQL string to be parsed. The package includes classes that represent clauses within the query string and methods for manipulating the strings within those clauses.
Currently, the only type of WQL expression that can be parsed is the SELECT expression. A SELECT expression contains the following parts:
SELECT statement
FROM clause
WHERE clause
The following figure shows the WBEM classes that represent the clauses in a WQL expression.
WBEM Query Lanuage |
WBEM Query Class |
---|---|
SELECT attribute_expression |
SelectList |
FROM table_attribute |
FromExp |
WHERE conditional_expression |
QueryExp |
WQL has been adapted to query data that is stored using the CIM data model. In the CIM model, information about objects is stored in CIM classes and CIM instances. CIM instances can contain properties, which have a name, data type, and value. WQL maps the CIM object model to SQL tables, as shown in the following table:
SQL |
WQL |
---|---|
Table |
CIM class |
Row |
CIM instance |
Column |
CIM property |
In CIM, a WQL expression could be expressed in the following form:
A more realistic example of a WQL expression follows:
SELECT * FROM Solaris_FileSystem WHERE (Name="home" OR Name="files") AND AvailableSpace > 2000000 |
The SelectExp class represents the SELECT statement.
The SELECT statement is the SQL statement for retrieving information, with a few restrictions and extensions specific to WQL. Although the SQL SELECT statement is typically used in the database environment to retrieve particular columns from tables, the WQL SELECT statement is used to retrieve instances of a single class. WQL does not support queries across multiple classes.
The SELECT expression identifies the search list. The SELECT statement can take one of the following forms:
SELECT Statement |
Selects |
---|---|
SELECT * |
All instances of the specified class and any of its subclasses. |
SELECT attr_exp, attr_exp...attr_exp |
Only instances of the specified class and any of its subclasses that contain the specifies identifiers. |
The FROM clause is represented by the abstract class, fromExp. Currently NonJoinExp is the only direct subclass of fromExp. The NonJoinExp represents FROM clauses with only one table (CIM class) to which the select operation should be applied.
The FROM clause identifies the class in which to search for instances that match the query string. In SQL terms, the FROM clause identifies a qualified attribute expression, which is the name of a class to search. A qualified attribute expression identifies the table and class. We currently support only non-join expressions, which means that a valid WQL FROM clause includes only a single class.
The QueryExp class is an abstract class whose subclasses represent conditional expressions which return a boolean value when a particular CIMInstance is applied to them.
The WHERE clause narrows the scope of a query. The WHERE clause contains a conditional expression, which can contain a property or key word, an operator, and a constant. All WHERE clauses must specify one of the predefined WQL operators.
The basic syntax for a WHERE clause appended to a SELECT statement follows:
SELECT FROM WHERE CIM instance CIM class conditional_expressionThe conditional expression in a WHERE clause takes the following form:
property operator constant
The following subclasses of the QueryExp class manipulate particular types of conditional expressions in the WHERE clause:
AndQueryExp
BinaryRelQueryExp
NotQueryExp
OrQueryExp
The conditional expression in the WHERE clause is represented by the QueryExp class. A conditional expression is represented by a tree structure. For example, the conditional expression (a=2 and b=3 or c=4) is represented by the tree structure shown in the following figure:
The QueryExp class returns only the top level of the query expression tree. In the above example, an OR QueryExp. The provider can then use methods within that class to get branches down the query expression tree.
The following methods are useful for providers that pass the WQL query string to another entity that parses the string:
canonizeDOC - Canonizes the expression into a Disjunction of Conjunctions form. (OR of ANDed comparison expressions). This enables handling of the expression as a List of Lists rather than a tree form, enabling ease of evaluation. For example: (x > 5 and y > 6) or (y > 6 and z=7)
canonizeCOD - Canonizes the expression into a Conjunction of Disjunctions form. (AND of ORed comparison expressions). This enables handling of the expression as a List of Lists rather than a tree form, enabling ease of evaluation. For example: (x > 5 or y > 6) and (y > 6 or z=7)
The general procedure for writing a provider that parses WQL queries using the Query APIs follows.
Initialize the WQL parser, for example:
/* Read query string passed to execQuery from the CIM Object Manager into an input data stream. */ ByteArrayInputStream in = new ByteArrayInputStream(query.getBytes()); /* Initialize the parser with the input data stream. */ WQLParser parser = new WQLParser(in);
Create a vector to store the result of the query. For example:
Vector result = new Vector();
Get the select expression from the query. For example:
/* querySpecification returns the WQL expression from the parser. (SelectExp)parser casts the WQL expression to a select expression. */ SelectExp q = (SelectExp)parser.querySpecification();
Get the select list from the select expression. For example:
/* Use the SelectList method in the SelectExp class to return the select list. The select list is the list of attributes, or CIM properties. */ SelectList attrs = q.getSelectList();
Get the From clause. For example:
/* Use the getFromClause method in the SelectExp class to return the From clause. Cast the From clause to a Non Join Expression, a table that represents a single CIM class. */ NonJoinExp from = (NonJoinExp)q.getFromClause();
Use the enumInstances method to return a deep enumeration of the class. For example:
/* Returns all instances, including inherited and local properties, belonging to the specified class (cc). */ Vector v = new Vector(); v = enumInstances(op, true, cc, true); ...
Iterate through the instances in the enumeration, matching the query expression and select list to each instance. For example:
/* Test whether the query expression in the WHERE clause matches the CIM instance. Apply the select list to the CIM instance and add any instance that matches the select list (list of CIM properties) to the result. */ for (int i = 0; i < v.size(); i++) { if ((where == null) || // If there is a WHERE clause (where.apply((CIMInstance)v.elementAt(i)) == true)) { result.addElement(attrs.apply((CIMInstance)v.elementAt(i))); ...
Return the query result. For example:
return result;
The sample program in Example 5–6 uses the Query APIs to parse the WQL string passed to it by the execQuerymethod. This program parses the Select Expression in the query string, does a deep enumeration of the class, and iterates through the instances in the enumeration, matching the query expression and select list to each instance. Finally, the program returns a vector containing the enumeration of the instances that match the query string.
/* * The execQuery method will support only limited queries * based upon partial key matching. An empty Vector is * returned if no entries are selected by the query. * * @param op The CIM object path of the CIM instance to be returned * @param query The CIM query expression * @param ql The CIM query language indicator * @param cc The CIM class reference * * @return A vector of CIM object instances * * @version 1.19 01/26/00 * @author Sun Microsystems, Inc. */ public Vector execQuery(CIMObjectPath op, String query, int ql, CIMClass cc) throws CIMException { ByteArrayInputStream in = new ByteArrayInputStream(query.getBytes()); WQLParser parser = new WQLParser(in); Vector result = new Vector(); try { SelectExp q = (SelectExp)parser.querySpecification(); SelectList attrs = q.getSelectList(); NonJoinExp from = (NonJoinExp)q.getFromClause(); QueryExp where = q.getWhereClause(); Vector v = new Vector(); v = enumInstances(op, false, cc, true); // filtering the instances for (int i = 0; i < v.size(); i++) { if ((where == null) || (where.apply((CIMInstance)v.elementAt(i)) == true)) { result.addElement(attrs.apply((CIMInstance)v.elementAt(i))); } } } catch (Exception e) { throw new CIMException(CIMException.CIM_ERR_FAILED, e.toString()); } return result; } // execQuery }