How to use RQL
RQL is an extension of FIQL (Feed Item Query Language). FIQL was proposed as an IETF Internet-Draft standard in 2007 as a URI-friendly syntax for expressing filters across the entries in a Web feed (https://tools.ietf.org/html/draft-nottingham-atompub-fiql-00).
RQL extends FIQL as follows:
Learn more about RQL:
Due to its similarity to URI query parameter notation and its brevity, we adopted the infix notation borrowed from FIQL rather than the alternate prefix notation.
Example:
and(eq(fld1,bill),gt(fld2,12),or(in(fld3,x,y,z),ne(fld4,sam*)))
fld1==bill;fld2=gt=12;(fld3=in=(x,y,z),fld4!=sam*)
The RQL query string appears in relevant URIs as:
/somethings?x=5&y=3&rql=fld1==bill;fld2=gt=12;(fld3=in=(x,y,z),fld4!=sam*)&z=2
Query expressions consist of zero or more predicates separated by a "Logical Operator".
A predicate is: "Property Name" "Comparison Operator" "Value"
;
,
The property names are always the API model property names, never the ORM property names they might map to.
For composite API property names, use “.” to specify the nesting, such as the Customer model’s CompanyInfo.Street1 or Readonly.CreationDate.
==
!=
=gt=
=ge=
=lt=
=le=
=in=
=out=
=hv=
Value strings must match the data type of the corresonding model property as follows:
true
or false
*
charactersFor string data types,*
can be used as follows:
fld1==*x
fld1==x*
fld1==*x*
fld1!=*x
fld1!=x*
fld1!=*x*
Properties of type string or nullable int, date, decimal can be tested for having a value.
companyinfo.name=hv=true
processdate=hv=false
Property names, operators and values are all case insensitive.
The following queries yield the same results:
companyinfo.name=gt=test
CompanyInfo.Name=Gt=Test
RQL proposes a simple, URI-friendly way to specify sorting as a comma-delimited list of property names with optional direction prefixes:
For example, to sort the Customer model by creation date descending then by customerid:
-readonly.creationdate,readonly.customerid
The sort string is specified as a separate URI query parameter as follows:
http://x.com/somethings?rql=fld1=gt=12&sort=fld2,-fld3&z=5
An RQL query is a string of Unicode characters in the form of an expression.
An RQL expression is composed of one or more predicates, related to each other with Boolean operators, each yielding Boolean values.
EBNF:
query ::= "" | expression expression ::= predicate | expression logic_op expression | "(" expression ")" predicate ::= qualified_identifier (comparison | like | in | hasvalue) comparison ::= (comp_op value) | (eq_op emptystring) like ::= eq_op wildstring in ::= in_op inlist hasvalue ::= "=hv=" bool logic_op ::= ";" | "," comp_op ::= eq_op | "=lt=" | "=le=" | "=gt=" | "=ge=" eq_op ::= "==" | "!=" in_op ::= "=in=" | "=out=" inlist ::= "(" value *("," value) ")" qual_ident ::= qualifier | qualifier "." qual_ident value ::= date | number | bool | string
A qualifier is a valid C# model property name; a dotted qual_ident is required for composite properties.
Terminals are described above in the "Value" section.
To view as a railroad track diagram, use http://www.bottlecaps.de/rr/ui. Paste the EBNF from above into the “Edit Grammar” tab then click the “View Diagram” tab.
Consider the following queries on the value of fld1:
Intent | Incorrect RQL | Problem |
---|---|---|
equals “x;y” | fld1==x;y |
Query rejected: “y” looks like an identifier without a predicate due to the semicolon “and” operator. |
ends with “x*” | fld1==*x* |
Query accepted: but semantics becomes “contains” rather than the intended “ends with”. |
starts with “x*” | fld1==x** |
Query rejected: ill-formed use of wildcards. |
is any of “a,”, “b)” or “c” | fld1=in=(a,,b),c) |
Query rejected: an empty value or a problem following the first closing paren. |
Both the FIQL and RQL standards specify URL encoding as the solution to each of these problems.
Intent | Correct RQL |
---|---|
equals “x;y” | fld1==x%3By |
ends with “x*” | fld1==*x%2A |
starts with “x*” | fld1==x%2A* |
is any of “a,”, “b)” or “c” | fld1=in=(a%2C,b%29,c) |
However, this introduces a new problem: how to form the query fld1 equals “x%3By”. In this case, we need to escape the “%”:
Intent | Correct RQL |
---|---|
equals “x%3By” | fld1==x%253By |
Though this works fine with RQL directly in the absence of HTTP, now introduce HTTP. Consider the query for fld1 equals “x%3By”, and the corresponding URL using the supposedly “Correct RQL” from above: http://server/resource?rql=fld1==x%253By
.
The server plumbing dutifully decodes the “rql” query parameter before passing it to the controller method, seeing the rql as “fld1==x%3By”, interpreted as fld1 equal “x;y”. Not the intent.
We solve this by recognizing the RQL expression is now riding inside a URL, and hence needs to be properly encoded within the URL, as follows: http://server/resource?rql=fld1==x%25253By
.
In other words, we encoded the “%” as “%25”. The server plumbing decodes the URL and the controller method now sees “fld1==x%253By”, interpreted as fld1 equals “x%3By” as intended.
Follow these simple rules when forming an RQL expression over HTTP:
Omit the last rule if not using HTTP.
This documentation is subject to change, and is updated often and without warning. The models documented may or may not be available to users now or in the future. Use this documentation at your own risk.
Contact api@3plcentral.com with any questions about this documentation.