Skip to main content

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:

  1. Textual Form: This is a string representation, similar to traditional SQL. It allows expressing conditions, operators, and references in a textual manner.
  2. 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 a referenceExpressionOperand.
  • 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 or false.
  • STRING: Text enclosed in single quotes (').

Sample Queries

  1. Basic comparison:

    object.property = 10
  2. Using negation:

    NOT(object.property = 'sample')
  3. Sub-query:

    object IN (anotherObject.property = 'value')
  4. Grouping:

    (object.property1 = 'value1' AND object.property2 = 'value2') OR object.property3 = 'value3'
  5. 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

  1. Field Selection:

    • Extract fields using DataItemClassInfo based on the data type.

      var firstNameField = DataItemClassInfo.GetClassInfo(typeof(Person)).GetField(nameof(Person.FirstName));
  2. Condition Creation:

    • Use the extracted fields to create conditional expressions.

      var firstNameCondition = new WhereComparisonExpression(firstNameField, WhereOperator.Equal, new WhereScalarOperand("John"));
  3. 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);