IQL Query Grammar

Simple IQL Query Specifications

While the Field-Name Class, View and Inheritance patterns are a particular strength of Inductor, they need not be used.  The fundamental strength of Inductor is actually the clean implementation of 'objective-SQL'.  That is, SQL using object references.

The IQL grammars is essentially just plain old SQL: select, from, where and orderBy.  The IQL syntax uses fully standard Java class and method references.  Familiar with SQL and ordinary Java principals?  Then you can write IQL queries largely without reference to the documentation.  Not familiar with the particulars of the underlying persistence manager classes?  Doesn't matter.  Inductor hides almost all of those details, subject to reasonable defaults.  To be sure, all of the persistence manager features are still easily accessible if needed.

A simple inline query:

... 
Query q = new Query(new JDODriver());

Field fname = q.newField(Person.class, "firstname"); 
Field lname = q.newField(Person.class, "lastname"); 
Field grade = q.newField(Person.class, "grade");

q.where(fname.like(firstName).and(lname.like(lastName).and(grade.gt(gradeLevel)); 
q.orderBy(lname.descending()); 
Collection c = q.execute(); 
...
 

... or, better, encapsulated in a convenience method:

public Collection findPerson(String firstName, String lastName, Integer gradeLevel) { 
    Query q = new Query(new JDODriver()); 
    Field fname = q.newField(Person.class, "firstname"); 
    Field lname = q.newField(Person.class, "lastname"); 
    Field grade = q.newField(Person.class, "grade"); 
    q.where(fname.like(firstName), 
            lname.like(lastName), 
            grade.isGreaterThan(gradeLevel) 
        ); 
    q.orderBy(lname.descending()); 
    return q.execute(); 
} 

Query Object/Driver Implementation

Query q = new Query(new JdoDriver());

The driver object, here represented by JDODriver, effectively encapsulates the persistence package specific dependencies.  Most persistence package default behaviors can be changed by method calls performed on the driver.

Field Objects/Persistence Mapping

Field fname = q.newField(Person.class, "firstname");

Person.class represents a standard persistence class implemented as appropriate for the specific persistence package used.

The persistence field references, "firstname", etc., identify the individual persistence field of a persistence class that is bound to the Field instance.  Rather than maintaining string values in each Field declaration, the preference is to define equivalent constants directly in the persistence-capable class:

Modified Persistence Capable Class:


// standard persistence class 
public class Person {  // modified merely to include a constants-based mapping 
public static final String FIRSTNAME = "firstname"; 
public static final String LASTNAME = "lastname"; 
public static final String GRADE = "gradelevel"; 
// standard persistence field declarations 
private String firstname; 
private String lastname; 
private int gradelevel; 
... 
} 

This makes the persistence class file the single, well-defined source code location of the only unchecked IQL dependent string literals -- much better than having content critical strings scattered throughout the code base.  Annotations may make it possible to remedy even this exposure.  The Field declarations for all IQL queries can then be re-written as just:

Type-Checked Field References:


Field fname = q.newField(Person.class, Person.FIRSTNAME); 
Field lname = q.newField(Person.class, Person.LASTNAME); 
Field grade = q.newField(Person.class, Person.GRADE);

From Clause

q.from(...);

Although required in standard SQL, Inductor does not require the use of a from clause for simple queries. Inferential identification of the target persistence class as identified in the Field objects is sufficient.

Where Clause

q.where(...);

Note the differences between the where clauses given in the above inline and method encapsulated queries.  Both actually define the same selection criteria.  In the first version, the selection is specified as a single serial set of constraints on a Field object.  The constraints, implemented as method calls, take Strings, Numbers, and other Fields, as appropriate, as parameters.  In the second version, three peer-criteria are combined using default implied and conjunctions.  Explicit and, or and not conjunctions can be specified.

In most instances where a Field is a valid parameter for a constraint method, an array of Fields can be provided.  Each array member Field, in turn, can be qualified by serial constraints.  The number of Field-based constraints that can be expressed in an IQL query is essentially unlimited.

OrderBy Clause

q.orderBy(lname.descending());

Identifies the Field and sort to be used in ordering the results.  Ascending is the default sort order.

Execute Clause

q.execute();

By default, execution returns a detached Collection containing the results of the query.  When a session or persistence manager instance is provided as a parameter to the driver, the query result is a Collection attached within the scope of the applicable session or persistence manager and any outstanding transaction.

Sections