Solaris WBEM SDK Developer's Guide

Chapter 5 Writing WBEM Queries

This chapter explains how to use the WBEM Query Language (WQL) and the query APIs to write queries, and includes the following topics:


Note -

For detailed information on the WBEM query APIs (javax.wbem.query), see file:/usr/sadm/lib/wbem/doc/index.html.


About the WBEM Query Language

The WBEM Query Language (WQL) is a subset of the standard American National Standards Institute Structured Query Language (ANSI SQL) with semantic changes to support WBEM in the Solaris environment.

The following table shows the mapping of SQL concepts to WQL.

Table 5-1 Mapping of SQL Concepts to WQL

SQL Concept 

WQL Representation 

Table 

CIM class 

Row 

CIM instance 

Column 

CIM property 


Note -

Like SQL, WQL statements use single (` ') quotation marks.


In the Solaris WBEM Services implementation, WQL is a retrieval-only language. You can use WQL 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.

Writing Queries

WBEM clients use WQL to query and filter data. When the data is served by a particular provider, the CIM Object Manager passes the client queries to the appropriate provider. You can search for instances that match a specified query in a particular class, or in all classes within a particular namespace.

For example, you can search for all instances of the Solaris_DiskDrive class that have a particular value for the Storage_Capacity property:



select * from Solaris_DiskDrive where Storage_Capacity = 1000

WQL Key Words

The Solaris WBEM SDK supports Level 1 WBEM SQL, which enables simple select operations without joins. The following table describes the supported WQL key words.

Table 5-2 Supported WQL Key Words

Key Word 

Description 

AND 

Combines two Boolean expressions and returns TRUE when both expressions are TRUE. 

FROM 

Specifies the classes that contain the properties listed in a SELECT statement. 

NOT 

Comparison operator used with NULL. 

OR 

Combines two conditions. When more than one logical operator is used in a statement, OR operators are evaluated after AND operators. 

SELECT 

Specifies the properties that are used in a query. 

WHERE 

Narrows the scope of a query. 

LIKE 

Generates a result set based on a minimum amount of information provided. 

SELECT Statement

You use the SELECT statement to retrieve instances of a single class and its subclasses. You can also specify the properties to retrieve and the conditions that must be met.


Note -

Currently, join operations are not supported.


The syntax for the SELECT statement is as follows:

SELECT list FROM class WHERE condition

The following table shows examples of using arguments in the SELECT clause to refine a search.

Table 5-3 Sample SELECT Statements

Example Query 

Description 

SELECT * FROM class

Selects all instances of the specified class and all of its subclasses. Each instance returned contains all the properties. 

SELECT PropertyA FROM class

Selects all instances containing PropertyA of the specified class and all of its subclasses.

SELECT PropertyA, PropertyB FROM class WHERE PropertyB=20

Selects all instances of the specified class and all of its subclasses where PropertyB=20. Each returned instance contains only PropertyA and PropertyB.

FROM Clause

The FROM clause identifies the class in which to search for instances that match the query string. Only non-joined expressions are supported, which means that a valid WQL FROM clause includes only a single class.

The FROM clause is represented by the abstract class, fromExp. Currently NonJoinExp is the only direct subclass of fromExp. The NonJoinExp subclass represents FROM clauses with only one table (CIM class) to which the SELECT operation is applied.

WHERE Clause

The WHERE clause narrows the scope of a query. This clause contains a conditional expression, which can contain a property or key word, an operator, and a constant.

The syntax for a WHERE clause appended to a SELECT statement is as follows:

SELECT CIMinstance FROM CIMclass WHERE conditional_expression 

The conditional_expression in the WHERE clause takes the following form:

 
property operator constant

The expression is composed of a property or key word, an operator, and a constant. You can append the WHERE clause to the SELECT statement using one of the following forms:

SELECT instance FROM class [[WHERE constant operator property]]

Valid WHERE clauses follow these rules:

Standard WQL Operators for WHERE Clauses

You can use the following standard WQL operators for a binary expression in the WHERE clause of a SELECT statement.

Table 5-4 WQL Operators for WHERE Clauses

Operator 

Description 

Equal to 

Less than 

Greater than 

<= 

Less than or equal to 

>= 

Greater than or equal to 

<> 

Not equal to 

Parsing Queries

The javax.wbem.query package contains utility classes that you use to parse WQL queries. The main class is SelectExp, whose constructor takes in a WQL query string. SelectExp parses the string and splits it into three parts. These parts can be retrieved using their corresponding accessor methods, as shown in the following table.

Query Part 

Accessor Method 

SELECT list 

getSelectList

FROM clause 

getFromClause

WHERE clause 

getWhereClause

The following query, onced parsed, has a SELECT list containing PropertyA and PropertyB. The FROM clause contains test_class, and the WHERE clause contains a parse tree of the conditional expression.



select PropertyA, PropertyB from test_class where 
       PropertyA > 20 and PropertyB < 30

SELECT List

The select list returned by the getSelectList method for each SelectExp is an instance of the SelectList class. This list specifies the properties that must be included in the selected instances, and consists of a list of AttributeExp instances. You can retrieve these AttributeExp instances using the elements method of SelectList. Each attribute denotes the name of a column that maps to a property of a CIMInstance in WQL. The AttributeExp has an apply method, which when passed in a CIMInstance, returns the value of the property that the AttributeExp represents. The SelectList has an apply method, which when passed in a CIMInstance, returns a CIMInstance containing only the properties that the SelectList AttributeExp instances denote.

FROM Clause

Currently, the only non-join expression that is allowed is the FROM clause. An instance of NonJoinExp is returned when the getFromClause method is invoked on SelectExp. The NonJoinExp represents the name of the class on which the selection is performed.

WHERE Clause

The WHERE clause is represented by QueryExp, an abstract class. The concrete subclasses are AndQueryExp, OrQueryExp, NotQueryExp, and BinaryRelQueryExp. Instances of these expressions are combined together in the form a parse tree that represents the original conditional expression.

The interior nodes of this tree consist of AndQueryExp, OrQueryExp, and NotQueryExp instances. These instances represent AND, OR, and NOT expressions, which in turn can consist of other AND, OR, and NOT expressions and binary relations.

The leaf nodes are BinaryRelQueryExp, which represent expressions of the form property operator constant. This represents a binary relation between a property and a constant value. You retrieve property operator constant using the getLeftValue, getRightValue, and getOperator methods.

Each QueryExp has an apply method, which when passed in a CIMInstance returns a boolean. The boolean is true if the conditional expression represented by the QueryExp is true for the CIMInstance. Otherwise, the boolean returns false.

The QueryExp has two other useful methods, canonizeDOC and canonizeCOD, which are used to simplify conditional expressions for further processing. The canonizeDOC method converts the parse tree from an arbitrary combination of ANDs and ORs to a canonical Disjunction of Conjunctions form (OR of ANDs). The canonizeCOD method converts the parse tree from an arbitrary combination of ANDs and ORs to canonical Conjunction of Disjunctions form (AND of ORs). These classes and methods are used by providers that need to filter instances based on input queries.


Note -

More details of these classes can be found in the Javadoc reference pages. See file:/usr/sadm/lib/wbem/doc/index.html.


Writing a Provider That Handles Queries

Following is an example provider program that uses the query APIs to parse the WQL string passed to it by the execQuery method. This program parses the select expression in the query string, performs 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.


Example 5-1 Provider That Handles Queries

/*
 * 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 CIMInstance[] execQuery(CIMObjectPath op, 
                       String query, 
                       String  ql,
                       CIMClass cc) 
           throws CIMException {

   Vector result = new Vector();
   try {
       SelectExp q = new SelectExp(query);
       SelectList attrs = q.getSelectList();
       NonJoinExp from = (NonJoinExp)q.getFromClause();
       QueryExp where = q.getWhereClause();

       CIMInstance[] v = enumerateInstances(op, false, true, 
                                            true, null, cc);

       // filtering the instances
       for (int i = 0; i < v.length; i++) {
               if ((where == null) || (where.apply(v[i]) == true)) {
                   result.addElement(attrs.apply(v[i]));
                } 
       }
   } catch (Exception e) {
       throw new CIMException(CIMException.CIM_ERR_FAILED, e.toString());
   }
   return (CIMInstance[])result.toArray();
 } // execQuery
}