RQL
How to use RQL

RQL
Resource Query Language

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:

prefix notation
and(eq(fld1,bill),gt(fld2,12),or(in(fld3,x,y,z),ne(fld4,sam*)))
infix notation
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

Predicates

Query expressions consist of zero or more predicates separated by a "Logical Operator".

A predicate is: "Property Name" "Comparison Operator" "Value"

Logical Operator

;
conjunction, meaning Boolean and
,
disjunction, meaning Boolean or
where “and” takes precedence over “or”, unless overridden by parentheses.

Property Name

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.

Comparison Operator

==
equals
!=
not equals
=gt=
greater than
=ge=
greater than or equal
=lt=
less than
=le=
less than or equal
=in=
similar to SQL “IN” clause
=out=
similar to SQL “NOT IN”
=hv=
has value, similar to SQL “IS NOT NULL” or “IS NULL” (see examples below)

Value

Value strings must match the data type of the corresonding model property as follows:

date
a string parsable by System.DateTime.Parse() such as 2013-07-30 or 2013-07-30T16:43:00 or 2013-07-30T16:43:00Z
number
a string parsable by either int.Parse() or decimal.Parse() depending on the data type of the target property
bool
true or false
string
a sequence of printable UNICODE characters
wildstring
a string containing one or more * characters
emptystring
a string containing no characters (allowed only on == and != operators)

Wildcards

For string data types,* can be used as follows:

fld1==*x
ends with x
fld1==x*
starts with x
fld1==*x*
contains x
fld1!=*x
does not end with x
fld1!=x*
does not start with x
fld1!=*x*
does not contain x

Has Value operator

Properties of type string or nullable int, date, decimal can be tested for having a value.

Select only records having a non-null, non-empty company name:
companyinfo.name=hv=true
Select only records with no processed date set:
processdate=hv=false

Case

Property names, operators and values are all case insensitive.

The following queries yield the same results:

companyinfo.name=gt=test
CompanyInfo.Name=Gt=Test

Sort

RQL proposes a simple, URI-friendly way to specify sorting as a comma-delimited list of property names with optional direction prefixes:

[ “+” | “-” ] property_name
where “+” means ascending, “- “means descending, and the default is ascending if not specified.
since + is the default, it's easier to leave it off;
  however, if you're really motivated to use +, make sure it is properly URL-encoded as %2b
  because + by itself in a query parameter means the space character

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

Formal Grammar

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.

Character Escape Sequences

Consider the following queries on the value of fld1:

IntentIncorrect RQLProblem
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.

IntentCorrect 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 “%”:

IntentCorrect 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:

  1. encode each predicate’s value by converting the following to their URL encoded value:
    • percent (%25)
    • exclamation (%21)
    • left paren (%28)
    • right paren (%29)
    • asterisk (%2A)
    • equal (%3D)
    • comma (%2C)
    • semicolon (%3B)
  2. affix an unencoded “*” for wildcard starts with, ends with and contains
  3. encode each “%” as “%25”

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.