Skip to content
Snippets Groups Projects
Verified Commit c78e268c authored by Timm Fitschen's avatar Timm Fitschen
Browse files

DOC: update query documentation, add syntax docs

parent a43f4756
No related branches found
No related tags found
2 merge requests!96DOC: Added CITATION.cff to the list of files in the release guide where the...,!71F find query
Pipeline #30813 passed
# Example queries
## Simple FIND Query
The following query will return any entity which has the name _ename_ and all its children.
`FIND ename`
The following queries are equivalent and will return any entity which has the name _ename_ and all its children, but only if they are genuin records. Of course, the returned set of entities (henceforth referred to as _resultset_) can also be restricted to recordtypes, properties and files.
`FIND RECORD ename`
`FIND RECORDS ename`
Wildcards use `*` for any characters or none at all. Wildcards for single characters (like the '_' wildcard from mysql) are not implemented yet.
`FIND RECORD en*` returns any entity which has a name beginning with _en_.
Regular expressions must be surrounded by _<<_ and '>>':
`FIND RECORD <<e[aemn]{2,5}>>`
`FIND RECORD <<[cC]am_[0-9]*>>`
*TODO* (Timm):
Describe escape sequences like `\\`, `\*`, `\<<` and `\>>`.
Currently, wildcards and regular expressions are only available for the _simple-find-part_ of the query, i. e. no wildcards/regexps for filters.
## Simple COUNT Query
This query counts entities which have certain properties.
`COUNT ename`
will return the number of entities which have the name _ename_ and all their children.
The syntax of the COUNT queries is equivalent to the FIND queries in any respect (this also applies to wildcards and regular expressions) but one: The prefix is to be `COUNT` instead of `FIND`.
Unlike the FIND queries, the COUNT queries do not return any entities. The result of the query is the number of entities which _would be_ returned if the query was a FIND query.
## Filters
### POV - Property-Operator-Value
The following queries are equivalent and will restrict the result set to entities which have a property named _pname1_ that has a value _val1_.
`FIND ename.pname1=val1`
`FIND ename WITH pname1=val1`
`FIND ename WHICH HAS A PROPERTY pname1=val1`
`FIND ename WHICH HAS A pname1=val1`
Again, the resultset can be restricted to records:
`FIND RECORD ename WHICH HAS A pname1=val1`
_currently known operators:_ `=, !=, <=, <, >=, >` (and cf. next paragraphes!)
#### Special Operator: LIKE
The _LIKE_ can be used with wildcards. The `*` is a wildcard for any (possibly empty) sequence of characters. Examples:
`FIND RECORD ename WHICH HAS A pname1 LIKE va*`
`FIND RECORD ename WHICH HAS A pname1 LIKE va*1`
`FIND RECORD ename WHICH HAS A pname1 LIKE *al1`
_Note:_ The _LIKE_ operator is will only produce expectable results with text properties.
#### Special Case: References
In general a reference can be addressed just like a POV filter. So
`FIND ename1.pname1=ename2`
will also return any entity named _ename1_ which references the entity with name or id _ename2_ via a reference property named _pname1_. However, it will also return any entity with a text property of that name with the string value _ename2_. In order to restrict the result set to reference properties one may make use of special reference operators:
_reference operators:_ `->, REFERENCES, REFERENCE TO`
The query looks like this:
`FIND ename1 WHICH HAS A pname1 REFERENCE TO ename2`
`FIND ename1 WHICH HAS A pname1->ename2`
#### Time Special Case: DateTime
_DateTime operators:_ `=, !=, <, >, IN, NOT IN`
##### `d1=d2`: Equivalence relation.
* ''True'' iff d1 and d2 are equal in every respect (same DateTime flavor, same fields are defined/undefined and all defined fields are equal respectively).
* ''False'' iff they have the same DateTime flavor but have different fields defined or fields with differing values.
* ''Undefined'' otherwise.
Examples:
* `2015-04-03=2015-04-03T00:00:00` is undefined.
* `2015-04-03T00:00:00=2015-04-03T00:00:00.0` is undefined (second precision vs. nanosecond precision).
* `2015-04-03T00:00:00.0=2015-04-03T00:00:00.0` is true.
* `2015-04-03T00:00:00=2015-04-03T00:00:00` is true.
* `2015-04=2015-05` is false.
* `2015-04=2015-04` is true.
##### `d1!=d2`: Intransitive, symmetric relation.
* ''True'' iff `d1=d2` is false.
* ''False'' iff `d1=d2` is true.
* ''Undefined'' otherwise.
Examples:
* `2015-04-03!=2015-04-03T00:00:00` is undefined.
* `2015-04-03T00:00:00!=2015-04-03T00:00:00.0` is undefined.
* `2015-04-03T00:00:00.0!=2015-04-03T00:00:00.0` is false.
* `2015-04-03T00:00:00!=2015-04-03T00:00:00` is false.
* `2015-04!=2015-05` is true.
* `2015-04!=2015-04` is false.
##### `d1>d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
###### [UTCDateTime](Datatype#datetime)
* ''True'' iff the time of d1 is after the the time of d2 according to [https://en.wikipedia.org/wiki/Coordinated_Universal_Time](UTC)
* ''False'' otherwise.
###### [SemiCompleteDateTime](Datatype#datetime)
* ''True'' iff `d1.ILB>d2.EUB` is true or `d1.ILB=d2.EUB` is true.
* ''False'' iff `d1.EUB<d2.ILB}} is true or {{{d1.EUB=d2.ILB` is true.
* ''Undefined'' otherwise.
Examples:
* `2015>2014` is true.
* `2015-04>2014` is true.
* `2015-01-01T20:15.00>2015-01-01T20:14` is true.
* `2015-04>2015` is undefined.
* `2015>2015-04` is undefined.
* `2015-01-01T20:15>2015-01-01T20:15:15` is undefined.
* `2014>2015` is false.
* `2014-04>2015` is false.
* `2014-01-01>2015-01-01T20:15:30` is false.
##### `d1<d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
###### [UTCDateTime](Datatype#datetime)
* ''True'' iff the time of d1 is before the the time of d2 according to [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time)
* ''False'' otherwise.
###### [SemiCompleteDateTime](Datatype#datetime)
* ''True'' iff `d1.EUB<d2.ILB` is true or `d1.EUB=d2.ILB` is true.
* ''False'' iff `d1.ILB>d2.EUB}} is true or {{{d1.ILB=d2.EUB` is true.
* ''Undefined'' otherwise.
Examples:
* `2014<2015` is true.
* `2014-04<2015` is true.
* `2014-01-01<2015-01-01T20:15:30` is true.
* `2015-04<2015` is undefined.
* `2015<2015-04` is undefined.
* `2015-01-01T20:15<2015-01-01T20:15:15` is undefined.
* `2015<2014` is false.
* `2015-04<2014` is false.
* `2015-01-01T20:15.00<2015-01-01T20:14` is false.
##### `d1 IN d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
###### [SemiCompleteDateTime](Datatype#datetime)
* ''True'' iff (`d1.ILB>d2.ILB` is true or `d1.ILB=d2.ILB` is true) and (`d1.EUB<d2.EUB` is true or `d1.EUB=d2.EUB` is true).
* ''False'' otherwise.
Examples:
* `2015-01-01 IN 2015` is true.
* `2015-01-01T20:15:30 IN 2015-01-01` is true.
* `2015-01-01T20:15:30 IN 2015-01-01T20:15:30` is true.
* `2015 IN 2015-01-01` is false.
* `2015-01-01 IN 2015-01-01T20:15:30` is false.
##### `d1 NOT IN d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
###### [SemiCompleteDateTime](Datatype#datetime)
* ''True'' iff (`d1.ILB IN d2.ILB` is false.
* ''False'' otherwise.
Examples:
* `2015 NOT IN 2015-01-01` is true.
* `2015-01-01 NOT IN 2015-01-01T20:15:30` is true.
* `2015-01-01 NOT IN 2015` is false.
* `2015-01-01T20:15:30 NOT IN 2015-01-01` is false.
* `2015-01-01T20:15:30 NOT IN 2015-01-01T20:15:30` is false.
##### Note
These semantics follow a three-valued logic with ''true'', ''false'' and ''undefined'' as truth values. Only ''true'' is truth preserving. I.e. only those expressions which evaluate to ''true'' pass the POV filter. `FIND ... WHICH HAS A somedate=2015-01` only returns entities for which `somedate=2015-01` is true. On the other hand, `FIND ... WHICH DOESN'T HAVE A somedate=2015-01` returns entities for which `somedate=2015-01` is false or undefined. Shortly put, `NOT d1=d2` is not equivalent to `d1!=d2`. The latter assertion is stronger.
#### Omitting the Property or the Value
One doesn't have to specify the property or the value at all. The following query filters the result set for entities which have any property with a value greater than _val1_.
`FIND ename WHICH HAS A PROPERTY > val1`
`FIND ename . > val1`
`FIND ename.>val1`
And for references...
`FIND ename1 WHICH HAS A REFERENCE TO ename2`
`FIND ename1 WHICH REFERENCES ename2`
`FIND ename1 . -> ename2`
`FIND ename1.->ename2`
The following query returns entities which have a _pname1_ property with any value.
`FIND ename WHICH HAS A PROPERTY pname1`
`FIND ename WHICH HAS A pname1`
`FIND ename WITH pname1`
`FIND ename . pname1`
`FIND ename.pname1`
### TransactionFilter
*Definition*
sugar:: `HAS BEEN` | `HAVE BEEN` | `HAD BEEN` | `WAS` | `IS`
negated_sugar:: `HAS NOT BEEN` | `HASN'T BEEN` | `WAS NOT` | `WASN'T` | `IS NOT` | `ISN'T` | `HAVN'T BEEN` | `HAVE NOT BEEN` | `HADN'T BEEN` | `HAD NOT BEEN`
by_clause:: `BY (ME | username | SOMEONE ELSE (BUT ME)? | SOMEONE ELSE BUT username)`
datetime:: A datetime string of the form `YYYY[-MM[-DD(T| )[hh[:mm[:ss[.nnn][(+|-)zzzz]]]]]]`
time_clause:: `[AT|ON|IN|BEFORE|AFTER|UNTIL|SINCE] (datetime) `
`FIND ename WHICH (sugar|negated_sugar)? (NOT)? (CREATED|INSERTED|UPDATED) (by_clause time_clause?| time_clause by_clause?)`
*Examples*
`FIND ename WHICH HAS BEEN CREATED BY ME ON 2014-12-24`
`FIND ename WHICH HAS BEEN CREATED BY SOMEONE ELSE ON 2014-12-24`
`FIND ename WHICH HAS BEEN CREATED BY erwin ON 2014-12-24`
`FIND ename WHICH HAS BEEN CREATED BY SOMEONE ELSE BUT erwin ON 2014-12-24`
`FIND ename WHICH HAS BEEN CREATED BY erwin`
`FIND ename WHICH HAS BEEN INSERTED SINCE 2021-04`
Note that `SINCE` and `UNTIL` are inclusive, while `BEFORE` and `AFTER` are not.
### File Location
Search for file objects by their location:
`FIND FILE WHICH IS STORED AT a/certain/path/`
#### Wildcards
_STORED AT_ can be used with wildcards similar to unix wildcards.
* `*` matches any characters or none at all, but not the directory separator `/`
* `**` matches any character or none at all.
* A leading `*` is short cut for `/**`
* A star directly between two other stars is ignored: `***` is the same as `**`.
* Escape character: `\` (E.g. `\\` is a literal backslash. `\*` is a literal star. But `\\*` is a literal backslash followed by a wildcard.)
Examples:
Find any files ending with `.acq`:
`FIND FILE WHICH IS STORED AT *.acq` or
`FIND FILE WHICH IS STORED AT **.acq` or
`FIND FILE WHICH IS STORED AT /**.acq`
Find files stored one directory below `/data/`, ending with `.acq`:
`FIND FILE WHICH IS STORED AT /data/*/*.acq`
Find files stored in `/data/`, ending with `.acq`:
`FIND FILE WHICH IS STORED AT /data/*.acq`
Find files stored in a directory at any depth in the tree below `/data/`, ending with `.acq`:
`FIND FILE WHICH IS STORED AT /data/**.acq`
Find any file in a directory which begins with `2016-02`:
`FIND FILE WHICH IS STORED AT */2016-02*/*`
### Back References
The back reference filters for entities that are referenced by another entity. The following query returns entities of the type _ename1_ which are referenced by _ename2_ entities via the reference property _pname1_.
* `FIND ename1 WHICH IS REFERENCED BY ename2 AS A pname1`
* `FIND ename1 WITH @ ename2 / pname1`
* `FIND ename1 . @ ename2 / pname1`
One may omit the property specification:
* `FIND ename1 WHICH IS REFERENCED BY ename2`
* `FIND ename1 WHICH HAS A PROPERTY @ ename2`
* `FIND ename1 WITH @ ename2`
* `FIND ename1 . @ ename2`
### Combining Filters with Propositional Logic
Any result set can be filtered by logically combining POV filters or back reference filters:
#### Conjunction (AND)
* `FIND ename1 WHICH HAS A PROPERTY pname1=val1 AND A PROPERTY pname2=val2 AND A PROPERTY...`
* `FIND ename1 WHICH HAS A PROPERTY pname1=val1 AND A pname2=val2 AND ...`
* `FIND ename1 . pname1=val1 & pname2=val2 & ...`
#### Disjunction (OR)
* `FIND ename1 WHICH HAS A PROPERTY pname1=val1 OR A PROPERTY pname2=val2 Or A PROPERTY...`
* `FIND ename1 WHICH HAS A PROPERTY pname1=val1 OR A pname2=val2 OR ...`
* `FIND ename1 . pname1=val1 | pname2=val2 | ...`
#### Negation (NOT)
* `FIND ename1 WHICH DOES NOT HAVE A PROPERTY pname1=val1`
* `FIND ename1 WHICH DOESN'T HAVE A pname1=val1`
* `FIND ename1 . NOT pname2=val2`
* `FIND ename1 . !pname2=val2`
#### ... and combinations with parentheses
* `FIND ename1 WHICH HAS A pname1=val1 AND DOESN'T HAVE A pname2<val2 AND ((WHICH HAS A pname3=val3 AND A pname4=val4) OR DOES NOT HAVE A (pname5=val5 AND pname6=val6))`
* `FIND ename1 . pname1=val1 & !pname2<val2 & ((pname3=val3 & pname4=val4) | !(pname5=val5 & pname6=val6))`
* `FIND ename1.pname1=val1&!pname2<val2&((pname3=val3&pname4=val4)|!(pname5=val5&pname6=val6))`
### A Few Important Expressions
* A:: The indistinct article. This is only syntactic suger. Equivalent expressions: `A, AN`
* AND:: The logical _and_. Equivalent expressions: `AND, &`
* FIND:: The beginning of the query.
* NOT:: The logical negation. Equivalent expressions: `NOT, DOESN'T HAVE A PROPERTY, DOES NOT HAVE A PROPERTY, DOESN'T HAVE A, DOES NOT HAVE A, DOES NOT, DOESN'T, IS NOT, ISN'T, !`
* OR:: The logical _or_. Equivalent expressions: `OR, |`
* RECORD,RECORDTYPE,FILE,PROPERTY:: Role expression for restricting the result set to a specific role.
* WHICH:: The marker for the beginning of the filters. Equivalent expressions: `WHICH, WHICH HAS A, WHICH HAS A PROPERTY, WHERE, WITH, .`
* REFERENCE:: This one is tricky: `REFERENCE TO` expresses a the state of _having_ a reference property. `REFERENCED BY` expresses the state of _being_ referenced by another entity.
* COUNT:: `COUNT` works like `FIND` but doesn't return the entities.
# Future
* *Sub Queries* (or *Sub Properties*): `FIND ename WHICH HAS A pname WHICH HAS A subpname=val`. This is like: `FIND AN experiment WHICH HAS A camera WHICH HAS A 'serial number'= 1234567890`
* *More Logic*, especially `ANY`, `ALL`, `NONE`, and `SUCH THAT` key words (and equivalents) for logical quantisation: `FIND ename1 SUCH THAT ALL ename2 WHICH HAVE A REFERENCE TO ename1 HAVE A pname=val`. This is like `FIND experiment SUCH THAT ALL person WHICH ARE REFERENCED BY THIS experiment AS conductor HAVE AN 'academic title'=professor.`
# CaosDB Query Language
**WIP This is going to be the specification. CQL tutorials are in the webui**
# CaosDB Query Language Examples
## Example queries
See syntax specification in :doc:`CaosDB Query Language Syntax<query-syntax>`.
## Simple FIND Query
The following query will return any record which has the name _ename_ and all
record children of any entity with that name.
### Simple FIND Query
The following query will return any entity which has the name _ename_ and all its children.
`FIND ename`
The following queries are equivalent and will return any entity which has the name _ename_ and all its children, but only if they are genuin records. Of course, the returned set of entities (henceforth referred to as _resultset_) can also be restricted to recordtypes, properties and files.
The following queries are equivalent to the former. Of course, the returned set of entities (henceforth referred to as _resultset_) can also be restricted to recordtypes, properties and files.
`FIND RECORD ename`
`FIND RECORDS ename`
Wildcards use `*` for any characters or none at all. Wildcards for single characters (like the '_' wildcard from mysql) are not implemented yet.
You can include all entities into the results by adding the `ENTITY` keyword:
`FIND ENTITY ename`.
`FIND RECORD en*` returns any entity which has a name beginning with _en_.
Wildcards use `*` for any characters or none at all. Wildcards for single characters (like the `_` wildcard from mysql) are not implemented yet.
Regular expressions must be surrounded by _<<_ and '>>':
`FIND en*` returns any record which has a name beginning with _en_.
`FIND RECORD <<e[aemn]{2,5}>>`
Regular expressions must be surrounded by _<<_ and _>>_:
`FIND RECORD <<[cC]am_[0-9]*>>`
`FIND <<e[aemn]{2,5}>>`
`FIND <<[cC]am_[0-9]*>>`
*TODO* (Timm):
Describe escape sequences like `\\ `, `\*`, `\<<` and `\>>`.
Describe escape sequences like `\\\\ `, `\*`, `\<<` and `\>>`.
Currently, wildcards and regular expressions are only available for the _simple-find-part_ of the query, i. e. no wildcards/regexps for filters.
### Simple COUNT Query
## Simple COUNT Query
Count queries count entities which have certain properties.
This query counts entities which have certain properties.
`COUNT ... ename ...`
`COUNT ename`
will return the number of entities which have the name _ename_ and all their children.
will return the number of records which have the name _ename_ and all record
children of any entity with that name.
The syntax of the COUNT queries is equivalent to the FIND queries in any respect (this also applies to wildcards and regular expressions) but one: The prefix is to be `COUNT` instead of `FIND`.
The syntax of the COUNT queries is equivalent to the FIND queries in any
respect (this also applies to wildcards and regular expressions) but one: The
prefix is to be `COUNT` instead of `FIND`.
Unlike the FIND queries, the COUNT queries do not return any entities. The result of the query is the number of entities which _would be_ returned if the query was a FIND query.
......@@ -43,7 +53,7 @@ Unlike the FIND queries, the COUNT queries do not return any entities. The resul
### POV - Property-Operator-Value
The following queries are equivalent and will restrict the result set to entities which have a property named _pname1_ that has a value _val1_.
The following queries are equivalent and will restrict the result set to records which have a property named _pname1_ that has a value _val1_.
`FIND ename.pname1=val1`
......@@ -53,21 +63,23 @@ The following queries are equivalent and will restrict the result set to entitie
`FIND ename WHICH HAS A pname1=val1`
Again, the resultset can be restricted to records:
Again, the resultset can be restricted to any other entity role as well:
`FIND RECORD ename WHICH HAS A pname1=val1`
`FIND RECORDTYPE ename WHICH HAS A pname1=val1`
_currently known operators:_ `=, !=, <=, <, >=, >` (and cf. next paragraphes!)
#### Special Operator: LIKE
The _LIKE_ can be used with wildcards. The `*` is a wildcard for any (possibly empty) sequence of characters. Examples:
The _LIKE_ can be used with wildcards. The `*` is a wildcard for any (possibly empty) sequence of characters.
`FIND RECORD ename WHICH HAS A pname1 LIKE va*`
Examples:
`FIND RECORD ename WHICH HAS A pname1 LIKE va*1`
`FIND ename WHICH HAS A pname1 LIKE va*`
`FIND RECORD ename WHICH HAS A pname1 LIKE *al1`
`FIND ename WHICH HAS A pname1 LIKE va*1`
`FIND ename WHICH HAS A pname1 LIKE *al1`
_Note:_ The _LIKE_ operator is will only produce expectable results with text properties.
......@@ -75,9 +87,9 @@ _Note:_ The _LIKE_ operator is will only produce expectable results with text pr
In general a reference can be addressed just like a POV filter. So
`FIND ename1.pname1=ename2`
`FIND ename1 WITH pname1=ename2`
will also return any entity named _ename1_ which references the entity with name or id _ename2_ via a reference property named _pname1_. However, it will also return any entity with a text property of that name with the string value _ename2_. In order to restrict the result set to reference properties one may make use of special reference operators:
will also return any record named _ename1_ which references the entity with name or id _ename2_ via a reference property named _pname1_. However, it will also return any entity with a text property of that name with the string value _ename2_. In order to restrict the result set to reference properties one may make use of special reference operators:
_reference operators:_ `->, REFERENCES, REFERENCE TO`
......@@ -88,7 +100,7 @@ The query looks like this:
`FIND ename1 WHICH HAS A pname1->ename2`
#### Time Special Case: DateTime
#### Special Case: DateTime
_DateTime operators:_ `=, !=, <, >, IN, NOT IN`
......@@ -116,7 +128,7 @@ Examples:
* `2015-04-03T00:00:00.0!=2015-04-03T00:00:00.0` is false.
* `2015-04-03T00:00:00!=2015-04-03T00:00:00` is false.
* `2015-04!=2015-05` is true.
* `2015-04!=2015-04` is false.
* `2015-04!=2015-04` is false
##### `d1>d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
......@@ -175,7 +187,7 @@ Examples:
* `2015 IN 2015-01-01` is false.
* `2015-01-01 IN 2015-01-01T20:15:30` is false.
##### `d1 NOT IN d2`: Non-symmetric relation.
##### `d1 NOT IN d2`: Transitive, non-symmetric relation.
Semantics depend on the flavors of d1 and d2. If both are...
###### [SemiCompleteDateTime](Datatype#datetime)
* ''True'' iff `d1.ILB IN d2.ILB` is false.
......@@ -193,7 +205,7 @@ These semantics follow a three-valued logic with ''true'', ''false'' and ''undef
#### Omitting the Property or the Value
One doesn't have to specify the property or the value at all. The following query filters the result set for entities which have any property with a value greater than _val1_.
One doesn't have to specify the property or the value at all. The following query filters the result set for records which have any property with a value greater than _val1_.
`FIND ename WHICH HAS A PROPERTY > val1`
......@@ -213,7 +225,7 @@ And for references...
`FIND ename1.->ename2`
The following query returns entities which have a _pname1_ property with any value.
The following query returns records which have a _pname1_ property with any value.
`FIND ename WHICH HAS A PROPERTY pname1`
......@@ -229,20 +241,15 @@ The following query returns entities which have a _pname1_ property with any val
*Definition*
sugar:: `HAS BEEN` | `HAVE BEEN` | `HAD BEEN` | `WAS` | `IS` |
sugar:: `HAS BEEN` | `HAVE BEEN` | `HAD BEEN` | `WAS` | `IS`
negated_sugar:: `HAS NOT BEEN` | `HASN'T BEEN` | `WAS NOT` | `WASN'T` | `IS NOT` | `ISN'T` | `HAVN'T BEEN` |
`HAVE NOT BEEN` | `HADN'T BEEN` | `HAD NOT BEEN`
negated_sugar:: `HAS NOT BEEN` | `HASN'T BEEN` | `WAS NOT` | `WASN'T` | `IS NOT` | `ISN'T` | `HAVN'T BEEN` | `HAVE NOT BEEN` | `HADN'T BEEN` | `HAD NOT BEEN`
by_clause:: `BY (ME | username | SOMEONE ELSE (BUT ME)? | SOMEONE ELSE BUT username)`
datetime:: A datetime string of the form `YYYY[-MM[-DD(T| )[hh[:mm[:ss[.nnn][(+|-)zzzz]]]]]]` or `TODAY`.
time_clause:: `[AT|ON|IN|BEFORE|AFTER|UNTIL|SINCE] (datetime) `
date:: A date string of the form `YYYY-MM-DD`
datetime:: A datetime string of the form `YYYY-MM-DD hh:mm:ss`
time_clause:: `ON ($date|$datetime) ` Here is plenty of room for more syntactic sugar, e.g. a `TODAY` keyword, and more funcionality, e.g. ranges.
`FIND ename WHICH ($sugar|$negated_sugar)? (NOT)? (CREATED|INSERTED|UPDATED|DELETED) (by_clause time_clause?| time_clause by_clause?)`
`FIND ename WHICH (sugar|negated_sugar)? (NOT)? (CREATED|INSERTED|UPDATED) (by_clause time_clause?| time_clause by_clause?)`
*Examples*
......@@ -256,8 +263,9 @@ The following query returns entities which have a _pname1_ property with any val
`FIND ename WHICH HAS BEEN CREATED BY erwin`
`FIND ename . CREATED BY erwin ON `
`FIND ename WHICH HAS BEEN INSERTED SINCE 2021-04`
Note that `SINCE` and `UNTIL` are inclusive, while `BEFORE` and `AFTER` are not.
### File Location
......@@ -297,7 +305,7 @@ Find any file in a directory which begins with `2016-02`:
### Back References
The back reference filters for entities that are referenced by another entity. The following query returns entities of the type _ename1_ which are referenced by _ename2_ entities via the reference property _pname1_.
The back reference filters for entities that are referenced by another entity. The following query returns records of the type _ename1_ which are referenced by _ename2_ entities via the reference property _pname1_.
* `FIND ename1 WHICH IS REFERENCED BY ename2 AS A pname1`
* `FIND ename1 WITH @ ename2 / pname1`
......@@ -401,4 +409,3 @@ Since Caosdb 0.2 entities are optionally version controlled. The query language
* *Sub Queries* (or *Sub Properties*): `FIND ename WHICH HAS A pname WHICH HAS A subpname=val`. This is like: `FIND AN experiment WHICH HAS A camera WHICH HAS A 'serial number'= 1234567890`
* *More Logic*, especially `ANY`, `ALL`, `NONE`, and `SUCH THAT` key words (and equivalents) for logical quantisation: `FIND ename1 SUCH THAT ALL ename2 WHICH HAVE A REFERENCE TO ename1 HAVE A pname=val`. This is like `FIND experiment SUCH THAT ALL person WHICH ARE REFERENCED BY THIS experiment AS conductor HAVE AN 'academic title'=professor.`
......@@ -17,6 +17,7 @@
# sys.path.insert(0, os.path.abspath('../caosdb'))
import sphinx_rtd_theme
from os.path import dirname, abspath
# -- Project information -----------------------------------------------------
......@@ -48,6 +49,7 @@ extensions = [
"sphinx.ext.autosectionlabel", # Allow reference sections using its title
"sphinx_rtd_theme",
"sphinxcontrib.plantuml", # PlantUML diagrams
"sphinx_a4doc", # antl4
]
# Add any paths that contain templates here, relative to this directory.
......@@ -223,3 +225,7 @@ autodoc_default_options = {
# -- Options for autosectionlabel --------------------------------------------
autosectionlabel_prefix_document = True
# -- Options for sphinx_a4doc ------------------------------------------------
a4_base_path = abspath(dirname(__file__) + '/../main/java/org/caosdb/server/query')
......@@ -11,7 +11,8 @@ Welcome to caosdb-server's documentation!
Getting started <README_SETUP>
Concepts <concepts>
tutorials
Query Language <CaosDB-Query-Language>
Query Language Examples <CaosDB-Query-Language>
Query Language Syntax <query-syntax>
administration
Development <development/devel>
Dependencies <DEPENDENCIES>
......
CaosDB Query Language Syntax
============================
This is the documentation of the CaosDB Query Language Syntax. The
authoritative specification of the syntax is the ANTLR4 grammar you can find in
the source code:
`CQLParser.g4 <https://gitlab.com/caosdb/caosdb-server/-/blob/main/src/main/java/org/caosdb/server/query/CQLParser.g4>`__
and
`CQLLexer.g4 <https://https://gitlab.com/caosdb/caosdb-server/-/blob/main/src/main/java/org/caosdb/server/query/CQLLexer.g4>`__
See examples in :doc:`Query Language<CaosDB-Query-Language>`.
.. a4:autogrammar:: CQLParser.g4
.. a4:autogrammar:: CQLLexer.g4
......@@ -21,93 +21,115 @@
*/
lexer grammar CQLLexer;
/** */
AS_A:
[Aa][Ss] (WHITE_SPACE_f? A)? WHITE_SPACE_f?
;
/** */
IS_REFERENCED:
(IS_f WHITE_SPACE_f?)? [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Dd] WHITE_SPACE_f?
;
/** */
BY:
[Bb][Yy] WHITE_SPACE_f?
;
/** */
fragment
OF_f:
[Oo][Ff]
;
/** */
fragment
ANY_f:
[Aa][Nn][Yy]
;
/** */
fragment
VERSION_f:
[Vv][Ee][Rr][Ss][Ii][Oo][Nn]
;
/** */
ANY_VERSION_OF:
(ANY_f WHITE_SPACE_f VERSION_f WHITE_SPACE_f OF_f) WHITE_SPACE_f?
;
/** */
SELECT:
[Ss][Ee][Ll][Ee][Cc][Tt] WHITE_SPACE_f? -> pushMode(SELECT_MODE)
;
/** */
INSERTED:
[Ii][Nn][Ss][Ee][Rr][Tt][Ee][Dd] WHITE_SPACE_f?
;
/** */
CREATED:
[Cc][Rr][Ee][Aa][Tt][Ee][Dd] WHITE_SPACE_f?
;
/** */
UPDATED:
[Uu][Pp][Dd][Aa][Tt][Ee][Dd] WHITE_SPACE_f?
;
/** */
ON:
[Oo][Nn] WHITE_SPACE_f?
;
/** */
IN:
[Ii][Nn] WHITE_SPACE_f?
;
/** */
AFTER:
[Aa][Ff][Tt][Ee][Rr] WHITE_SPACE_f?
;
/** */
BEFORE:
[Bb][Ee][Ff][Oo][Rr][Ee] WHITE_SPACE_f?
;
/** */
UNTIL:
[Uu][Nn][Tt][Ii][Ll] WHITE_SPACE_f?
;
/** */
SINCE:
[Ss][Ii][Nn][Cc][Ee] WHITE_SPACE_f?
;
/** */
IS_STORED_AT:
(IS_f WHITE_SPACE_f?)? [Ss][Tt][Oo][Rr][Ee][Dd] (WHITE_SPACE_f? AT)? WHITE_SPACE_f?
;
/** */
AT:
[Aa][Tt] WHITE_SPACE_f?
;
/** */
FIND:
[Ff][Ii][Nn][Dd] WHITE_SPACE_f?
;
/** */
COUNT:
[Cc][Oo][Uu][Nn][Tt] WHITE_SPACE_f?
;
/** */
AND:
(
(
......@@ -117,6 +139,7 @@ AND:
) WHITE_SPACE_f?
;
/** */
OR:
(
(
......@@ -126,22 +149,27 @@ OR:
) WHITE_SPACE_f?
;
/** */
LPAREN:
'(' WHITE_SPACE_f?
;
/** */
RPAREN:
')' WHITE_SPACE_f?
;
/** */
SINGLE_QUOTE_START:
'\'' -> pushMode(SINGLE_QUOTE_MODE)
;
/** */
DOUBLE_QUOTE_START:
'"' -> pushMode(DOUBLE_QUOTE_MODE)
;
/** */
OPERATOR:
'='
| '<'
......@@ -153,115 +181,138 @@ OPERATOR:
| [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee]([Ss]|WHITE_SPACE_f? [Tt][Oo]) (WHITE_SPACE_f? A {_input.LA(1) == ' '}?)? {setText("->");}
;
/** */
LIKE:
[Ll][Ii][Kk][Ee] WHITE_SPACE_f?
;
/** */
IS_NULL:
IS_f WHITE_SPACE_f NULL_f WHITE_SPACE_f?
;
/** */
IS_NOT_NULL:
IS_f WHITE_SPACE_f NOT_f WHITE_SPACE_f NULL_f WHITE_SPACE_f?
;
/** */
fragment
NULL_f:
[Nn][Uu][Ll][Ll]
;
/** */
fragment
DOES_f:
[Dd][Oo][Ee][Ss]
;
/** */
fragment
NOT_f:
[Nn][Oo][Tt]
;
/** */
fragment
DOESNT_f:
DOES_f WHITE_SPACE_f? NOT_f
| DOES_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
ISNT_f:
IS_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
WERE_f:
[Ww][Ee][Rr][Ee]
;
/** */
fragment
WERENT_f:
WERE_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
HAVENT_f:
HAVE_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
HADNT_f:
HAD_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
HAD_f:
[Hh][Aa][Dd]
;
/** */
fragment
HAVE_f:
[Hh][Aa][Vv][Ee]
;
/** */
fragment
HAS_f:
[Hh][Aa][Ss]
;
/** */
fragment
HASNT_f:
HAS_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
BEEN_f:
[Bb][Ee][Ee][Nn]
;
/** */
fragment
HAVE_A_f:
HAVE_f (WHITE_SPACE? A)?
;
/** */
fragment
DO_f:
[Dd][Oo]
;
/** */
fragment
DONT_f:
DO_f NOT_f
| DO_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
fragment
WAS_f:
[Ww][Aa][Ss]
;
/** */
fragment
WASNT_f:
WAS_f [Nn] SINGLE_QUOTE [Tt]
;
/** */
NEGATION:
(
'!'
......@@ -277,46 +328,57 @@ NEGATION:
) WHITE_SPACE_f?
;
/** */
WITH:
[Ww][Ii][Tt][Hh] WHITE_SPACE_f?
;
/** */
THE:
[Tt][Hh][Ee] WHITE_SPACE_f?
;
/** */
GREATEST:
[Gg][Rr][Ee][Aa][Tt][Ee][Ss][Tt] WHITE_SPACE_f?
;
/** */
SMALLEST:
[Ss][Mm][Aa][Ll][Ll][Ee][Ss][Tt] WHITE_SPACE_f?
;
/** */
A:
[Aa][Nn]? WHITE_SPACE_f?
;
/** */
ME:
[Mm][Ee] WHITE_SPACE_f?
;
/** */
SOMEONE:
[Ss][Oo][Mm][Ee][Oo][Nn][Ee] WHITE_SPACE_f?
;
/** */
ELSE:
[Ee][Ll][Ss][Ee] WHITE_SPACE_f?
;
/** */
WHERE:
[Ww][Hh][Ee][Rr][Ee] WHITE_SPACE_f?
;
/** */
WHICH:
[Ww][Hh][Ii][Cc][Hh] WHITE_SPACE_f?
;
/** */
HAS_A:
(
(HAS_f | HAD_f | HAVE_f | WERE_f | WAS_f | IS_f)
......@@ -327,236 +389,293 @@ HAS_A:
) WHITE_SPACE_f?
;
/** */
PROPERTY:
[Pp][Rr][Oo][Pp][Ee][Rr][Tt]([Yy]|[Ii][Ee][Ss]) WHITE_SPACE_f?
;
/** */
RECORDTYPE:
[Rr][Ee][Cc][Oo][Rr][Dd][Tt][Yy][Pp][Ee]([Ss])? WHITE_SPACE_f?
;
/** */
RECORD:
[Rr][Ee][Cc][Oo][Rr][Dd]([Ss])? WHITE_SPACE_f?
;
/** */
FILE:
[Ff][Ii][Ll][Ee]([Ss])? WHITE_SPACE_f?
;
/** */
ENTITY:
[Ee][Nn][Tt][Ii][Tt]([Yy]|[Ii][Ee][Ss]) WHITE_SPACE_f?
;
/** */
QUERYTEMPLATE:
[Qq][Uu][Ee][Rr][yY][Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee] WHITE_SPACE_f?
;
/** */
fragment
IS_f:
[Ii][Ss]
;
/** */
fragment
WHITE_SPACE_f:
[ \t\n\r]+
;
/** */
WHITE_SPACE:
[ \t\n\r]+
;
/** */
fragment
DOUBLE_QUOTE:
'"'
;
/** */
fragment
SINGLE_QUOTE:
'\''
;
/** */
REGEXP_MARKER:
'#'
;
/** */
REGEXP_BEGIN:
'<<'
;
/** */
REGEXP_END:
'>>'
;
/** */
ID:
[Ii][Dd] WHITE_SPACE_f?
;
/** */
SLASH:
'/'
;
/** */
STAR:
'*'
;
/** */
DOT:
'.'
;
/** */
QMARK:
'?' WHITE_SPACE_f?
;
/** */
BUT:
[Bb][Uu][Tt] WHITE_SPACE_f?
;
/** */
ESC_REGEXP_END:
ESC_MARKER
'>>' WHITE_SPACE_f?
;
/** */
ESC_STAR:
ESC_MARKER
'*' WHITE_SPACE_f?
;
/** */
ESC_BS:
ESC_MARKER
'\\' WHITE_SPACE_f?
;
/** */
fragment
ESC_MARKER:
'\\'
;
/** */
TODAY:
[Tt][Oo][Dd][Aa][Yy] WHITE_SPACE_f?
;
/** */
HYPHEN:
'-'
;
/** */
COLON:
':'
;
/** */
NUM:
NUM_f
| DOT NUM_f
| NUM_f DOT NUM_f
;
/** */
NUM_f:
('0'..'9')+
;
/** */
TXT:
('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-' {_input.LA(1) != '>'}? | '+' | '&' | ';' | ',' | '$' | ':' | '%' | '^' | '~' {_input.LA(1) != '='}? | '`' | '´' | 'ö' | 'ä' | 'ß' | 'ü' | 'Ö' | 'Ä' | 'Ü' | '@' | '[' | ']' | '{' | '}' )+
;
/** */
UNKNOWN_CHAR: . ;
/** */
mode SINGLE_QUOTE_MODE;
/** */
SINGLE_QUOTE_ESCAPED_CHAR:
ESC_MARKER
( '\'' | '\\' | '*' )
;
/** */
SINGLE_QUOTE_END:
'\'' -> mode(DEFAULT_MODE)
;
/** */
SINGLE_QUOTE_STAR:
'*'
;
/** */
SINGLE_QUOTE_ANY_CHAR:
~('\''|'\\'|'*')+
;
/** */
mode DOUBLE_QUOTE_MODE;
/** */
DOUBLE_QUOTE_ESCAPED_CHAR:
ESC_MARKER
( '"' | '\\' | '*' )
;
/** */
DOUBLE_QUOTE_END:
'"' -> mode(DEFAULT_MODE)
;
/** */
DOUBLE_QUOTE_STAR:
'*'
;
/** */
DOUBLE_QUOTE_ANY_CHAR:
~('"'|'\\'|'*')+
;
/** */
mode SELECT_DOUBLE_QUOTED;
/** */
SELECT_DOUBLE_QUOTE_ESCAPED:
ESC_MARKER
'"'
;
/** */
SELECT_DOUBLE_QUOTE_END:
'"' WHITE_SPACE_f? {setText("");} -> mode(SELECT_MODE)
;
/** */
SELECT_DOUBLE_QUOTE_TXT:
.
;
/** */
mode SELECT_SINGLE_QUOTED;
/** */
SELECT_SINGLE_QUOTE_ESCAPED:
ESC_MARKER
'\''
;
/** */
SELECT_SINGLE_QUOTE_END:
'\'' WHITE_SPACE_f? {setText("");} -> mode(SELECT_MODE)
;
/** */
SELECT_SINGLE_QUOTE_TXT:
.
;
/** */
mode SELECT_MODE;
/** */
FROM:
[Ff][Rr][Oo][Mm]([ \t\n\r])* -> mode(DEFAULT_MODE)
;
/** */
SELECT_ESCAPED:
ESC_MARKER
( '"' | '\\' | '\'' | ',' | '.' ) {setText(getText().substring(1));}
;
/** */
SELECT_DOT:
'.'
WHITE_SPACE_f?
;
/** */
SELECT_DOUBLE_QUOTE:
'"' {setText("");} -> mode(SELECT_DOUBLE_QUOTED)
;
/** */
SELECT_SINGLE_QUOTE:
'\'' {setText("");} -> mode(SELECT_SINGLE_QUOTED)
;
/** */
SELECT_COMMA:
','
WHITE_SPACE_f?
;
/** */
SELECTOR_TXT:
.
;
......@@ -29,6 +29,9 @@ options { tokenVocab = CQLLexer; }
import java.util.List;
}
/**
* This is the root of the CQL grammar.
*/
cq returns [Query.Type t, List<Query.Selection> s, Query.Pattern e, Query.Role r, EntityFilterInterface filter, VersionFilter v]
@init{
$s = null;
......@@ -56,6 +59,9 @@ cq returns [Query.Type t, List<Query.Selection> s, Query.Pattern e, Query.Role r
EOF
;
/**
* For versioned queries.
*/
version returns [VersionFilter v]
@init{
$v = null;
......@@ -64,6 +70,9 @@ version returns [VersionFilter v]
ANY_VERSION_OF {$v = VersionFilter.ANY_VERSION;}
;
/**
* The comma-separated list of selected (sub)properties of a SELECT query.
*/
prop_sel returns [List<Query.Selection> s]
@init{
$s = new LinkedList<Query.Selection>();
......@@ -73,6 +82,9 @@ prop_sel returns [List<Query.Selection> s]
(SELECT_COMMA prop_subsel {$s.add($prop_subsel.sub);})*
;
/**
* The (sub-)selections (e.g. geolocation.longitude) of a SELECT query.
*/
prop_subsel returns [Query.Selection sub]:
selector_txt {$sub = new Query.Selection($selector_txt.text);}
(
......@@ -80,6 +92,9 @@ prop_subsel returns [Query.Selection sub]:
)?
;
/**
* Rule for the allowed characters of a prop_subsel.
*/
selector_txt:
(
SELECT_DOUBLE_QUOTE
......@@ -94,6 +109,9 @@ selector_txt:
( SELECTOR_TXT | SELECT_ESCAPED )+
;
/**
* The entity role.
*/
role returns [Query.Role r]:
RECORDTYPE {$r = Query.Role.RECORDTYPE;}
| RECORD {$r = Query.Role.RECORD;}
......@@ -103,6 +121,9 @@ role returns [Query.Role r]:
| ENTITY {$r = Query.Role.ENTITY;}
;
/**
* The filters of a FIND, SELECT, or COUNT query.
*/
entity_filter returns [EntityFilterInterface filter]
@init{
$filter = null;
......@@ -126,6 +147,9 @@ entity_filter returns [EntityFilterInterface filter]
)?
;
/**
* WHICH keyword and syntactic sugar.
*/
which_exp:
WHICH (HAS_A (PROPERTY)?)?
| HAS_A (PROPERTY)?
......@@ -134,6 +158,9 @@ which_exp:
| DOT WHITE_SPACE?
;
/**
* Collection of different filters.
*/
filter_expression returns [EntityFilterInterface efi]
:
backreference (subproperty {((Backreference) $backreference.ref).setSubProperty($subproperty.subp);})? {$efi = $backreference.ref;}
......@@ -145,6 +172,9 @@ filter_expression returns [EntityFilterInterface efi]
| negation {$efi=$negation.n;}
;
/**
* ID Filter (e.g. id > 10123).
*/
idfilter returns [IDFilter filter] locals [String o, String v, String a]
@init{
$a = null;
......@@ -164,6 +194,9 @@ idfilter returns [IDFilter filter] locals [String o, String v, String a]
)?
;
/**
* Transaction filter (e.g INSERTED BY ME).
*/
transaction returns [TransactionFilter filter] locals [String type, TransactionFilter.Transactor user, String time, String time_op]
@init{
$time = null;
......@@ -186,6 +219,9 @@ transaction returns [TransactionFilter filter] locals [String type, TransactionF
)
;
/**
* The transactor (e.g. "user1", or "ME").
*/
transactor returns [TransactionFilter.Transactor t]
:
BY
......@@ -200,6 +236,9 @@ transactor returns [TransactionFilter.Transactor t]
)
;
/**
* A user name or a user name pattern.
*/
username returns [Query.Pattern ep] locals [int type]
@init{
$type = Query.Pattern.TYPE_NORMAL;
......@@ -211,6 +250,9 @@ username returns [Query.Pattern ep] locals [int type]
( STAR {$type = Query.Pattern.TYPE_LIKE;} | ~(STAR | WHITE_SPACE) )+
;
/**
* Time or timeframe of a transaction (for the transaction filter).
*/
transaction_time returns [String tqp, String op]
@init {
$op = "(";
......@@ -232,8 +274,10 @@ transaction_time returns [String tqp, String op]
)
;
/*
* not fully compliant with iso 8601 (TODO)
/**
* A date time or a fragment of a date time.
*
* Not fully compliant with iso 8601 (TODO).
*/
datetime
:
......@@ -259,6 +303,10 @@ datetime
)?
;
/**
* The property-operator-value filter (e.g. temperator > 240°C) and
* (optionally) subfilters.
*/
pov returns [POV filter] locals [Query.Pattern p, String o, String v, String a]
@init{
$p = null;
......@@ -300,6 +348,9 @@ pov returns [POV filter] locals [Query.Pattern p, String o, String v, String a]
;
/**
* Wrapper for a filter on referenced entities.
*/
subproperty returns [SubProperty subp]
@init{
$subp = null;
......@@ -308,6 +359,9 @@ subproperty returns [SubProperty subp]
subproperty_filter {$subp = new SubProperty($subproperty_filter.filter);}
;
/**
* The actual filter on referenced entities.
*/
subproperty_filter returns [EntityFilterInterface filter]
@init{
$filter = null;
......@@ -329,7 +383,9 @@ subproperty_filter returns [EntityFilterInterface filter]
)?
;
/**
* The backreference filter (e.g. REFERENCED BY ...).
*/
backreference returns [Backreference ref] locals [Query.Pattern e, Query.Pattern p]
@init{
$e = null;
......@@ -349,6 +405,9 @@ backreference returns [Backreference ref] locals [Query.Pattern e, Query.Pattern
WHITE_SPACE?
;
/**
* Stored-at filter for the path of files.
*/
storedat returns [StoredAt filter] locals [String loc]
@init{
$loc = null;
......@@ -362,6 +421,9 @@ storedat returns [StoredAt filter] locals [String loc]
WHITE_SPACE?
;
/**
* Combine other filters with a logical AND.
*/
conjunction returns [Conjunction c]
@init{
$c = new Conjunction();
......@@ -399,6 +461,9 @@ conjunction returns [Conjunction c]
)+
;
/**
* Combine other filter with a logical OR.
*/
disjunction returns [Disjunction d]
@init{
$d = new Disjunction();
......@@ -435,6 +500,9 @@ disjunction returns [Disjunction d]
)+
;
/**
* Negation of another filter.
*/
negation returns [Negation n]
@init{
}
......@@ -454,6 +522,9 @@ negation returns [Negation n]
)
;
/**
* An entity's full name, id, or a pattern for a name.
*/
entity returns [Query.Pattern ep]
:
regexp_pattern {$ep = $regexp_pattern.ep;}
......@@ -464,6 +535,10 @@ entity returns [Query.Pattern ep]
| ( ~(ENTITY |WHITE_SPACE | DOT) )+ {$ep = new Query.Pattern((String) $text.trim(), Query.Pattern.TYPE_NORMAL);}
;
/**
* A regexp pattern.
*/
regexp_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
@init{
$sb = new StringBuffer();
......@@ -474,6 +549,9 @@ regexp_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
REGEXP_END {$ep = new Query.Pattern((String) $sb.toString(), Query.Pattern.TYPE_REGEXP);}
;
/**
* A like pattern (e.g. "*oxide").
*/
like_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
@init{
$sb = new StringBuffer();
......@@ -485,6 +563,9 @@ like_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
{$ep = new Query.Pattern((String) $text, Query.Pattern.TYPE_LIKE);}
;
/**
* A Property's name, id or a pattern of a name.
*/
property returns [Query.Pattern pp, String agg]locals [StringBuffer sb]
@init{
$sb = new StringBuffer();
......@@ -502,6 +583,9 @@ property returns [Query.Pattern pp, String agg]locals [StringBuffer sb]
WHITE_SPACE?
;
/**
* Expression for minumum or maximum.
*/
minmax returns [String agg]
:
(THE?? (
......@@ -510,6 +594,9 @@ minmax returns [String agg]
))
;
/**
* A property value.
*/
value returns [String str]
:
number_with_unit {$str = $number_with_unit.text;}
......@@ -518,6 +605,9 @@ value returns [String str]
WHITE_SPACE?
;
/**
* A number with a unit (e.g. 20m).
*/
number_with_unit
:
HYPHEN??
......@@ -525,6 +615,9 @@ number_with_unit
(WHITE_SPACE?? unit)?
;
/**
* A unit from a physical system of units or any other kind of system.
*/
unit
:
(~(WHITE_SPACE | WHICH | HAS_A | WITH | WHERE | DOT | AND | OR | RPAREN ))
......@@ -533,6 +626,9 @@ unit
NUM SLASH (~(WHITE_SPACE))+
;
/**
* A files path.
*/
location returns [String str]
:
atom {$str = $atom.ep.str;}
......@@ -540,6 +636,9 @@ location returns [String str]
(~WHITE_SPACE)+ {$str = $text; }
;
/**
* An atomic string or pattern.
*/
atom returns [Query.Pattern ep]
:
double_quoted {$ep = $double_quoted.ep;}
......@@ -547,6 +646,9 @@ atom returns [Query.Pattern ep]
| (~(WHITE_SPACE | DOT | RPAREN | LPAREN ))+ {$ep = new Query.Pattern($text, Query.Pattern.TYPE_NORMAL);}
;
/**
* A single-quoted string or pattern.
*/
single_quoted returns [Query.Pattern ep] locals [StringBuffer sb, int patternType]
@init{
$sb = new StringBuffer();
......@@ -567,6 +669,9 @@ single_quoted returns [Query.Pattern ep] locals [StringBuffer sb, int patternTyp
SINGLE_QUOTE_END
;
/**
* A double-quoted string or pattern.
*/
double_quoted returns [Query.Pattern ep] locals [StringBuffer sb, int patternType]
@init{
$sb = new StringBuffer();
......
......@@ -5,8 +5,8 @@ RUN apt-get update && \
plantuml \
python3-pip screen libpam0g-dev unzip curl shunit2 \
python3-sphinx \
&& \
pip3 install javasphinx recommonmark sphinx-rtd-theme sphinxcontrib-plantuml
RUN pip3 install javasphinx recommonmark sphinx-rtd-theme sphinxcontrib-plantuml sphinx-a4doc
# Alternative, if javasphinx fails because python3-sphinx is too recent:
# (`_l` not found):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment