Queries
Overview
OOQL (Object-Oriented Query Language) is a domain-specific language designed for querying objects in a structured manner. It provides constructs to perform complex queries on objects and their properties, and also allows for grouping, negation, and sub-querying.
The are two Forms of OOQL:
- Textual Form: This is a string representation, similar to traditional SQL. It allows expressing conditions, operators, and references in a textual manner.
- Typed/Formal Form: This is more oriented towards .NET code and involves the usage of classes, objects, and methods to construct the query.
Textual Form
Where Expression
A whereExpression
is the core of any OOQL query. It's composed of one of the following:
- A
groupExpression
- A
subQueryExpression
- A
negateExpression
Group Expression
A groupExpression
is composed of multiple andGroupExpression
combined using the OR
operator. This facilitates the logical 'AND' and 'OR' operations within queries.
Comparison Expression
A comparisonExpression
represents the most basic form of filtering in the OOQL, comparing a variable operand or identifier against another operand using a comparison operator.
Negate Expression
Negates the result of a whereExpression
.
Sub-Query Expression
Allows for a nested whereExpression
, enabling hierarchical querying.
Using Expression
Represents the USING
keyword, useful for querying with specific parameters or conditions.
Reference Expression
Denotes the REFERENCE
keyword, likely to retrieve or specify certain object references.
Operators
- Logical Operators:
AND
,OR
- Comparison Operators:
EQUAL
,NOTEQUAL
,LT
,LTEQ
,GT
,GTEQ
,LIKE
,CONTAINS
,NOTCONTAINS
- Special Operators:
NEGATEOPERATOR
,SUBQUERYOPERATOR
,USINGOPERATOR
,REFERENCEOPERATOR
Operands
- Variable Operand: Represents an object's property or a chain of properties (like
object.property1.property2
). - Right Expression Operand: Can be either a
scalarExpressionOperand
or areferenceExpressionOperand
. - Scalar Expression Operand: Represents primitive data types including integers, floats, dates, booleans, and strings.
Data Types
- INTEGER: Whole numbers.
- FLOAT: Decimal numbers.
- DATETIME: Date and time values enclosed in
#
. - BOOLEAN: Represents
true
orfalse
. - STRING: Text enclosed in single quotes (
'
).
Sample Queries
-
Basic comparison:
object.property = 10
-
Using negation:
NOT(object.property = 'sample')
-
Sub-query:
object IN (anotherObject.property = 'value')
-
Grouping:
(object.property1 = 'value1' AND object.property2 = 'value2') OR object.property3 = 'value3'
-
Using the
USING
keyword:USING 'sampleParameter'
Typed/Formal Form
1. WhereExpression
- Represents a condition in the query.
- Base class for other conditional expressions.
2. WhereOperand
- Represents a value or a reference in a condition.
- Can be a scalar value, field, or reference.
3. WhereOperator
- Enumerates the different comparison operations, e.g., Equal, NotEqual, GreaterThan, etc.
4. WhereLogicator
- Enumerates logical operations used to combine conditions, e.g., And, Or.
Basic Usage
Query Construction
-
Field Selection:
-
Extract fields using
DataItemClassInfo
based on the data type.var firstNameField = DataItemClassInfo.GetClassInfo(typeof(Person)).GetField(nameof(Person.FirstName));
-
-
Condition Creation:
-
Use the extracted fields to create conditional expressions.
var firstNameCondition = new WhereComparisonExpression(firstNameField, WhereOperator.Equal, new WhereScalarOperand("John"));
-
-
Combining Conditions:
-
Combine multiple conditions using the
WhereGroupExpression
.var finalQuery = new WhereGroupExpression(WhereLogicator.And, firstNameCondition, lastNameCondition);
-
Advanced Usage
Sub-Queries
-
Utilize
WhereSubQueryExpression
to represent sub-queries.var subQueryCondition = new WhereComparisonExpression(authorCountryField, WhereOperator.Equal, new WhereScalarOperand("UK"));
var finalQuery = new WhereSubQueryExpression(bookAuthorField, subQueryCondition);
Negations
-
Use the
WhereNegateExpression
for negating conditions.var finalQuery = new WhereNegateExpression(categoryCondition);
Object Relationships
-
Queries can span across related objects.
var productCategoryField = DataItemClassInfo.GetClassInfo(typeof(OrderLines)).GetField(nameof(OrderLines.Product.Category));
The typed/formal form of OOQL gives developers the power to leverage their coding skills for constructing queries. It ensures type-safety and clarity, making it a robust choice for object-oriented data model querying.
Examples
1. Basic Query
Textual Form:
FirstName = 'John' AND LastName = 'Doe'
Typed/Formal Form (C#):
var firstNameField = DataItemClassInfo.GetClassInfo(typeof(Person)).GetField(nameof(Person.FirstName));
var lastNameField = DataItemClassInfo.GetClassInfo(typeof(Person)).GetField(nameof(Person.LastName));
var firstNameCondition = new WhereComparisonExpression(firstNameField, WhereOperator.Equal, new WhereScalarOperand("John"));
var lastNameCondition = new WhereComparisonExpression(lastNameField, WhereOperator.Equal, new WhereScalarOperand("Doe"));
var finalQuery = new WhereGroupExpression(WhereLogicator.And, firstNameCondition, lastNameCondition);
2. Using References:
Textual Form:
Customer.Reference = 'C12345'
Typed/Formal Form (C#):
var customerReferenceField = DataItemClassInfo.GetClassInfo(typeof(Invoice)).GetField(nameof(Invoice.Customer.Reference));
var referenceCondition = new WhereComparisonExpression(customerReferenceField, WhereOperator.Equal, new WhereScalarOperand("C12345"));
var finalQuery = referenceCondition;
3. Using Sub-Queries
Textual Form:
Book.Author IN (Author.Country = 'UK')
Typed/Formal Form (C#):
var authorCountryField = DataItemClassInfo.GetClassInfo(typeof(Author)).GetField(nameof(Author.Country));
var bookAuthorField = DataItemClassInfo.GetClassInfo(typeof(Book)).GetField(nameof(Book.Author));
var subQueryCondition = new WhereComparisonExpression(authorCountryField, WhereOperator.Equal, new WhereScalarOperand("UK"));
var finalQuery = new WhereSubQueryExpression(bookAuthorField, subQueryCondition);
4. Negation
Textual Form:
NOT Product.Category = 'Electronics'
Typed/Formal Form (C#):
var categoryField = DataItemClassInfo.GetClassInfo(typeof(Product)).GetField(nameof(Product.Category));
var categoryCondition = new WhereComparisonExpression(categoryField, WhereOperator.Equal, new WhereScalarOperand("Electronics"));
var finalQuery = new WhereNegateExpression(categoryCondition);
5. Using Object Relationships:
Textual Form:
Order.OrderDate > '01-01-2023' AND OrderLines.Product.Category = 'Books'
Typed/Formal Form (C#):
var orderDateField = DataItemClassInfo.GetClassInfo(typeof(Order)).GetField(nameof(Order.OrderDate));
var productCategoryField = DataItemClassInfo.GetClassInfo(typeof(OrderLines)).GetField(nameof(OrderLines.Product.Category));
var dateCondition = new WhereComparisonExpression(orderDateField, WhereOperator.GreaterThan, new WhereScalarOperand(new DateTime(2023, 1, 1)));
var categoryCondition = new WhereComparisonExpression(productCategoryField, WhereOperator.Equal, new WhereScalarOperand("Books"));
var finalQuery = new WhereGroupExpression(WhereLogicator.And, dateCondition, categoryCondition);