EQL Syntax for database query
WebVella ERP support entity query language (EQL) for retrieving data from database. To make easier understanding of that topic, lets assume we have the following imaginary entity structures and relation between them.
Entity: demo_customer
id | name | contact |
---|---|---|
9e1c2d3c-8ce4-4c8f-a651-e54421baa09c | Alfreds Futterkiste | Maria Anders |
fc1ca2ea-f3d6-4bf5-8853-bd4a44bf37f9 | Alessandro Moratti | Alessandro Moratti |
d9b17096-dfa1-4a8d-a7f6-00b74ee329f6 | Antonio Moreno Taquería | Antonio Moreno |
a919418d-bc36-4673-9f2b-839ae6ac8e38 | Around the Horn | Thomas Hardy |
Entity: demo_address
id | customer_id | address | city | country |
---|---|---|---|---|
2c104d0f-d40f-48ee-8964-33265176a70c | 9e1c2d3c-8ce4-4c8f-a651-e54421baa09c | Tauentzienstrasse 98 | Berlin | Germany |
65349ebd-f6ac-4612-a127-f32ebe4f23fd | 9e1c2d3c-8ce4-4c8f-a651-e54421baa09c | Anry Barbuys 12 | Plovdiv | Bulgaria |
86344903-513b-4fb3-a14e-9931083c2bd6 | fc1ca2ea-f3d6-4bf5-8853-bd4a44bf37f9 | Viale Cassala 1 | Milano | Italy |
81991d8b-32f2-4d5d-9854-55407cd03026 | d9b17096-dfa1-4a8d-a7f6-00b74ee329f6 | Mataderos 2312 | México D.F. | Mexico |
0ecaa5f0-c846-4d33-9ba0-ad032205511e | a919418d-bc36-4673-9f2b-839ae6ac8e38 | 120 Hanover Sq. | London | UK |
Entity relation: customer_1n_address
This is one to many relation between both entities on field demo_customer.id
and demo_address.customer_id
The SELECT Statement
The select statement is used to select data from ERP entities. Its syntax is very similar to the SQL Select statement, so for developers with SQL knowledge will be very easy to use it.
SELECT field1,field2,...
FROM entity
Here, field1, field2
.. are the field names of the entity you want to select from. if you want to select all the fields available in the entity
,
use the following syntax:
SELECT * FROM entity
Example
The following EQL statement selects the only name
field from demo_customer
entity.
SELECT name FROM demo_customer
The result from eql select queries will be list of EntityRecord objects. Each EntityRecord property can be a List of EntityRecords. So the result of eql execution is a tree structure and cannot be represented by table printing (like sql results). That's why we will print result as serialized to json list of objects.
The execution of the specified above query produces the following result:
[
{
"id" : "9e1c2d3c-8ce4-4c8f-a651-e54421baa09c",
"name": "Alfreds Futterkiste"
},
{
"id" : "fc1ca2ea-f3d6-4bf5-8853-bd4a44bf37f9",
"name": "Alessandro Moratti"
},
{
"id" : "d9b17096-dfa1-4a8d-a7f6-00b74ee329f6",
"name": "Antonio Moreno Taquería"
},
{
"id" : "a919418d-bc36-4673-9f2b-839ae6ac8e38",
"name": "Around the Horn",
}
]
You probably notice that we wanted to get only name
field from entity demo_customer, but result contains 2 fields (id
field included).
Thats because, internally ERP always need the id
field and adds it to select query.
Unlike sql, eql select doesn't support joins syntax.
We use relations to include related records in each record.
Relations are used by their name and $ character decoration in front of the name ($relation_name
).
SELECT field1,field2, $relation_name.fieldX1, $relation_name.fieldX2
FROM entity
The result will look like:
[
{
"id": "...",
"field1": "...",
"field2": "...",
"$relation_name":
[
{ "id": "...",
"fieldX1" : "...",
"fieldX2" : "..."
},
{ "id": "...",
"fieldX1" : "...",
"fieldX2" : "..."
},
...
]
},
...
]
Here we select fields1,field2
from entity and in each entity record in the result we have an additional property with name $relation_name
which is a list of entity records.
That property contains the list of records, related to upper record, using the relation rules.
Using more real looking data from structure specified above will make sample more simple to perception. So lets say we want to select all customers with their addresses. The eql select statement looks like that:
SELECT *, $customer_1n_address.*
FROM demo_customer
and will produce following result:
[
{
"id" : "9e1c2d3c-8ce4-4c8f-a651-e54421baa09c",
"name": "Alfreds Futterkiste",
"contact": "Maria Anders",
"$customer_1n_address":
[
{
"id": "2c104d0f-d40f-48ee-8964-33265176a70c",
"customer_id": "9e1c2d3c-8ce4-4c8f-a651-e54421baa09c",
"address": "Tauentzienstrasse 98",
"city": "Berlin",
"country": "Germany"
},
{
"id": "65349ebd-f6ac-4612-a127-f32ebe4f23fd",
"customer_id": "9e1c2d3c-8ce4-4c8f-a651-e54421baa09c",
"address": "Anry Barbuys 12",
"city": "Plovdiv",
"country": "Bulgaria"
}
]
},
{
"id" : "fc1ca2ea-f3d6-4bf5-8853-bd4a44bf37f9",
"name": "Alessandro Moratti",
"contact": "Alessandro Moratti",
"$customer_1n_address":
[
{
"id": "86344903-513b-4fb3-a14e-9931083c2bd6",
"customer_id": "fc1ca2ea-f3d6-4bf5-8853-bd4a44bf37f9",
"address": "Viale Cassala 1",
"city": "Milano",
"country": "Italy"
}
]
},
{
"id" : "d9b17096-dfa1-4a8d-a7f6-00b74ee329f6",
"name": "Antonio Moreno Taquería",
"contact": "Antonio Moreno",
"$customer_1n_address":
[
{
"id": "81991d8b-32f2-4d5d-9854-55407cd03026",
"customer_id": "d9b17096-dfa1-4a8d-a7f6-00b74ee329f6",
"address": "Mataderos 2312",
"city": "México D.F.",
"country": "Mexico"
}
]
},
{
"id" : "a919418d-bc36-4673-9f2b-839ae6ac8e38",
"name": "Around the Horn",
"contact" : "Thomas Hardy",
"$customer_1n_address":
[
{
"id": "0ecaa5f0-c846-4d33-9ba0-ad032205511e",
"customer_id": "a919418d-bc36-4673-9f2b-839ae6ac8e38",
"address": "120 Hanover Sq.",
"city": "London",
"country": "UK"
}
]
}
]
The erp translate eql to sql ,with joins inside, according specified relation direction, fields and entities. Sql joins direction are automatically
recognized by entity of the upper record. Only one specific case exists when direction should be specified - when a relation from one entity to same entity is used.
Then from origin to target direction is automatically used. In order to switch direction of the generated sql join use double $ with the relation name
(e.g. $$relation_name
).
Eql also supports multiple, connected through, relations. Here is an example
SELECT *,
$relation1.fieldX1, $relation1.fieldX2, ...
$relation.$relation2.fieldY1,$relation.$relation2.fieldY2...
FROM entity
Or if you want all field and extend with 3-rd relation
SELECT *, $relation1.*, $relation.$relation2.*, $relation.$relation2.$relation3.*
FROM entity
Last query will result in something like that:
[
{
"id": "...",
"$relation1":
[
{
"id": "...",
"$relation2" :
[
{
"id": "...",
"$relation3" :
[
{
"id": "...",
...
}
...
]
...
}
...
],
...
}
...
],
...
}
...
]
The WHERE Clause
The WHERE clause is used to filter records. The WHERE clause is used to extract only those records that fulfill a specified condition.
SELECT field1,field2,...
FROM entity
WHERE condition
the following statement select all the customers with contact
equals to 'Thomas Hardy', in the entity demo_customer
SELECT *
FROM demo_customer
WHERE contact = 'Thomas Hardy'
Execution of the specified query will produce the following result:
[
{
"id" : "a919418d-bc36-4673-9f2b-839ae6ac8e38",
"name": "Around the Horn",
"contact" : "Thomas Hardy"
}
]
In our ERP application development, mostly parameterized statements are used. Parameters, like in sql, are specified by @
character in front of their names.
Here is the same example as previous, where parameter @contact
replaces the literal 'Thomas Hardy'. The parameter values are provided by
ERP datasources internally or by using EQL related classes and structures in API to execute queries.
SELECT *
FROM demo_customer
WHERE contact = @contact
Here is the list of supported where condition operators:
operator | description |
---|---|
= | returns true, if the field value is EQUAL to right side literal, number or parameter |
> | returns true, if the field value is GREATER than right side literal, number or parameter |
>= | returns true, if the field value is GREATER OR EQUAL than right side literal, number or parameter |
< | returns true, if the field value is LOWER than right side literal, number or parameter |
<= | returns true, if the field value is LOWER OR EQUAL than right side literal, number or parameter |
<> | returns true, if the field value is NOT EQUAL to right side literal, number or parameter |
!= | returns true, if the field value is NOT EQUAL to right side literal, number or parameter |
AND | logical AND compares between two expressions or field value (if boolean) and expression and returns true when both are true. |
OR | Logical OR compares between two expressions or field value(if boolean) and expression and returns true when one of them is true |
CONTAINS | if text field content contains text (right operand literal or parameter) returns true |
STARTSWITH | if text field content value starts with text (right operand literal or parameter), returns true |
~ | case sensitive regex search operator, which search field value for pattern (provided as right operand) matches, returns true if matches found |
~* | case insensitive regex search operator, which search field value for pattern (provided as right operand) matches, returns true if matches found |
!~ | case sensitive regex search operator, which search field value for pattern (provided as right operand) matches, returns true if matches are not found |
!~* | case insensitive regex search operator, which search field value for pattern (provided as right operand) matches, returns true if matches are not found |
@@ | full-text search, searches in field value for specified text (right operand) using FTS index. if match found returns true |
All the operators have equal precedence with only Logical AND and OR operators.
The OR operator have lowest precedence. The logical AND operator have lower precedence than others, but higher than logical OR.
You can use standard braces to control operator precedence. Also the following example shows, how you can use relation in where clause.
Only note that first level relations can be used only ($relation1.$relation2
.... not supported).
SELECT *, $customer_1n_address.*
FROM demo_customer
WHERE ( contact = 'Thomas Hardy' OR name STARTSWITH 'Around' ) AND $customer_1n_address.country CONTAINS 'UK'
You can use multiple expressions and combine them with logical operators. In example
SELECT *
FROM demo_customer
WHERE ( contact = 'Thomas Hardy' ) AND ( name STARTSWITH 'Around' )
In EQL compare to NULL (note its upper case only) is also done with operators =
, <>
and !=
.
SELECT *, $customer_1n_address.*
FROM demo_customer
WHERE contact = NULL
Important note: WHERE condition statements can only have a field name as left operand, so unlike SQL, the following code will produce error:
SELECT *
FROM demo_customers
WHERE 'Germany' = country
-- or
SELECT *
FROM demo_customers
WHERE @country = country
The ORDER BY Keyword
The ORDER BY keyword is used to sort the result in ascending or descending order. The ORDER BY keyword sorts the records in ascending order by default (ASC). To sort the records in descending order, use the DESC keyword. You can also use multiple fields to order by, each by is its own direction. The sorting field precedence is from left to right. Left has highest precedence. Ordering fall to next field sorting, if previous field record values are equal.
SELECT *
FROM entity
ORDER BY field1, field2 DESC
The eql support parametrized ordering (which is not supported in sql). You can use parameter to specify field name or order direction.
SELECT *
FROM entity
ORDER BY @order_field @order_direction
and even more customizable with multiple parameters and even field from relation
SELECT *
FROM entity
ORDER BY @order_field1 @order_direction1, @order_field2 @order_direction2, $relationX.fieldX DESC ....
These parameters are verified during translation from eql to sql.
The PAGE and PAGESIZE Keyword
These keywords allow you to retrieve just a portion of the records that are generated by the rest of the query. Both keywords are always used in combination (using only one of them will result in error). Both values should be positive integer numbers.
SELECT *
FROM entity
PAGE 1 -- number
PAGESIZE 10 --number
Keyword PAGE specify which page of records should be returned, while the PAGESIZE specify the records count in single page. First page return records from 1 to PAGESIZE and so on. Similar to ORDER BY keyword, PAGE and PAGESIZE accept parameterized input
SELECT *
FROM entity
PAGE @page
PAGESIZE @pagesize
Note: When using these keywords, it is important to use an ORDER BY that sorts the result records into a unique order. Otherwise you will get an unpredictable subset of the query's records.