Inductor provides a number of facilities, usable alone or in combination, for implementing simple to quite complex query specifications. With reasonable choice, and subject to one caveat, the query specification remains quite readable regardless of the logical complexity of the query. The Inductor facilities include:
For a given Field, the IQL criteria constraints that will be applied to that Field are specified serially by a trailing sequence of Field method calls. By default, an and relationship is implied as joining each successive constraint.
(String literal parameters are used for illustration. Field parameters can also be specified as variables and, in either case, can be of type String or Number.)
employee.name.startsWith("B").endsWith("s").like("%ses%").neq("Branses");
employee.name LIKE 'B%' AND employee.name LIKE '%s' AND employee.name LIKE '%ses%' AND employee.name <> 'Branses'
q.where(employee.firstname.eq("Bill"),
employee.lastname.eq("Jones"),
employee.department.eq("Home") );
q.where(employee.firstname.eq("Bill"),
employee.lastname.eq("Jones"),
new Field[] { employee.department.eq("Home"),
employee.paygrade.gt(new Integer(4)),
employee.shift.gteq(new Integer(2)),
employee.storelocation.eq("CA")
} );
q.where(new Field[] { employee.firstname.eq("Bill"),
employee.lastname.eq("Jones"),
employee.department.eq("Home"),
employee.paygrade.gt(new Integer(4)),
employee.shift.gteq(new Integer(2)),
employee.storelocation.eq("CA")
} );
The three conjunctions and(), or(), and not() can be used in-line to connect criteria acting on a given field and to define subclauses that relate additional Fields to the root Field of the conjunction.
q.where(employee.firstname.startsWith("B").or().startsWith("C"),
employee.firstname.startsWith("J").or().startsWith("K"),
employee.number.eq(12).or().gt(45) );
q.where(employee.firstname.eq("Bill").or(),
employee.lastname.eq("Smith") );
q.where(employee.firstname.startsWith("B").and(
employee.lastname.endsWith("s").or(
employee.number.gt(45).or().eq(12) )));
employee.firstname LIKE 'B%' AND ( employee.lastname LIKE '%s' OR ( employee.number > 45 OR employee.number = 12 ) )
q.where(employee.firstname.startsWith("Will"),
employee.lastname.endsWith("s").or(
new Field[] { employee.department.eq("Home"),
employee.title.startsWith("Chief").or(
employee.number.gt(45).or().eq(12)
)
}
)
);
employee.firstname LIKE 'Will%' AND
employee.lastname LIKE '%s' OR
( ( employee.department = 'Home' AND
employee.title LIKE 'Chief%' OR
( employee.number > 45 OR employee.number = 12 )
)
)
Just as with standard SQL, Inductor permits completely correct, but relatively incomprehensible queries to be constructed. Unlike standard SQL, however, Inductor supports a number of effective strategies for making clear even the most complex of queries.
q.where(person.zip.gt(aZip1).and(
person.fname.like(firstName).and(
person.lname.like(lastName)))));
q.where(person.zip.gt(aZip1),
person.fname.like(firstName),
person.lname.like(lastName) );
q.where(new Field[] { project.jobtype.eq(aJob).and(
new Field[] {
project.city.eq(jobCity),
project.state.eq(jobState),
project.zip.eq(jobZip)
}).or(),
project.contractor.eq(jobContractor).or(),
project.workdate.gt(jobDate).and(),
project.invoice.gteq(invoiceNumb).and(
new Field[] {
project.invoicetype.eq(jobType),
project.workcode.gt(jobCode)
})
});
Field[] validLoc = new Field[] {
project.city.eq(jobCity),
project.state.eq(jobState),
project.zip.eq(jobZip) };
Field[] validJob = new Field[] {
project.invoicetype.eq(jobType),
project.workcode.eq(jobCode) };
q.where(new Field[] {
project.jobtype.eq(aJob).and(validLoc).or(),
project.contractor.eq(jobContractor).or(),
project.workdate.gt(jobDate).and(),
project.invoice.gteq(invoiceNumb).and(validJob)
});
Unfortunately, nothing is for free: there is a caveat. Just one, though, and it is pretty obscure.
// this illustrates the caveat - the or() creates a child subclause
// and both parent a child start with the same Field zip ...
q.where(person.zip.gt(aZip1).or(new Field[] {
person.zip.lt(aZip2),
person.lname.like(lastName)
})
);
// this is OK, though
q.where(person.zip.gt(aZip1).or(new Field[] {
person.lname.like(lastname),
person.zip.lt(aZip2)
})
);
// peers work fine - effectively the same SQL logic
q.where(person.zip.gt(aZip1).or(),
new Field[] {
person.zip.lt(aZip2),
person.lname.like(lastname)
}
);