Reference: 17. Expressions and Testing Values
SPARQL supports expressions, which can be used to compute values and filter query results. In particular, expressions can be used in the following circumstances:
:filter clause.:bind clause, in an [expr var] form.:group-by clause, either as a freestanding expression or in an [expr var] form.:select, :order-by or :having clause.In Flint, an expression is either a list of the form (op expr...), similar to Clojure functions, or a terminal, which can be a variable, an IRI or a literal.
Other than certain exceptions, like exists and not-exists, non-terminal expressions only accept other expressions as arguments.
The following is an example of an expression in Flint:
(if (< ?x ?y) (str ?x) (* 2 (+ 3 4)))
which is translated into SPARQL as:
IF((?x < ?y), STR(?x), (2 * (3 + 4)))
NOTE: Due to the complexity of SPARQL type semantics, Flint does not make any attempt to typecheck or validate expression arguments or return values.
SPARQL supports boolean and arithmetic operations, with accept one or more expression arguments and return boolean or numeric values. Like all expressions, boolean and arithmetic operations are written in Clojure's prefix order in Flint, but are translated to SPARQL's infix order. (The exceptions are the unary not operator, as well as SPARQL's unary + and - that are not supported in Flint.)
The in and not-in operations are special boolean operations that are equivalent to (or (= expr expr1) (= expr expr2) ...) and (and (not= expr expr1) (not= expr expr2) ...), respectively.
| Flint | SPARQL Form | Arglist | Reference |
|---|---|---|---|
not | !(expr) | [expr] | |
or | (expr \|\| expr) | [expr & exprs] | 17.4.1.5 |
and | (expr && expr) | [expr & exprs] | 17.4.1.6 |
= | (expr = expr) | [expr expr] | 17.4.1.7 |
not= | (expr != expr) | [expr expr] | |
< | (expr < expr) | [expr expr] | |
> | (expr > expr) | [expr expr] | |
<= | (expr <= expr) | [expr expr] | |
>= | (expr >= expr) | [expr expr] | |
+ | (expr + expr + ...) | [expr & exprs] | |
- | (expr - expr - ...) | [expr & exprs] | |
* | (expr * expr * ...) | [expr & exprs] | |
/ | (expr / expr / ...) | [expr & exprs] | |
in | (expr IN (expr, ...)) | [expr & exprs] | 17.4.1.9 |
not-in | (expr NOT IN (expr, ...)) | [expr & exprs] | 17.4.1.10 |
SPARQL accepts a number of built-in functions, which are translated from Flint's (fname expr expr ...) form to SPARQL's FNAME(expr, expr, ...) form. This section contains a list of all non-aggregate built-in expressions, grouped together by argument and return types.
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
if | IF | [expr expr expr] | 17.4.1.2 |
coalesce | COALESCE | [& expr] | 17.4.1.3 |
datatype | DATATYPE | [expr] | 17.4.2.7 |
Unlike most expressions, exists and not-exists only accept graph patterns as arguments. The following example:
[:filter (exists [[?person :foaf/name ?name]])]
becomes:
FILTER EXISTS {
?person foaf:name ?name .
}
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
exists | EXISTS | [graph-pattern] | 17.4.1.4 |
not-exists | NOT EXISTS | [graph-pattern] | 17.4.1.4 |
| Flint | SPARQL name | Arglist | Reference |
|---|---|---|---|
iri | IRI | [expr] | 17.4.2.8 |
uri | URI | [expr] | 17.4.2.8 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
bnode | BNODE | [] or [expr] | 17.4.2.9 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
uuid | UUID | [] | 17.4.2.12 |
struuid | STRUUID | [] | 17.4.2.13 |
String-specific predicates are listed under Strings and Language Maps. Note that bound takes a variable instead of another expression as its argument.
| Flint | SPARQL name | Arglist | Reference |
|---|---|---|---|
bound | BOUND | [var] | 17.4.1.1 |
sameterm | SAMETERM | [expr expr] | 17.4.1.8 |
iri? | isIRI | [expr] | 17.4.2.1 |
uri? | isURI | [expr] | 17.4.2.1 |
blank? | isBLANK | [expr] | 17.4.2.2 |
literal? | isLITERAL | [expr] | 17.4.2.3 |
numeric? | isNUMERIC | [expr] | 17.4.2.4 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
str | STR | [expr] | 17.4.2.5 |
lang | LANG | [expr] | 17.4.2.6 |
strdt | STRDT | [expr expr] | 17.4.2.10 |
strlang | STRLANG | [expr expr] | 17.4.2.11 |
strlen | STRLEN | [expr] | 17.4.3.2 |
substr | SUBSTR | [expr expr] or [expr expr expr] | 17.4.3.3 |
ucase | UCASE | [expr] | 17.4.3.4 |
lcase | LCASE | [expr] | 17.4.3.5 |
strstarts | STRSTARTS | [expr expr] | 17.4.3.6 |
strends | STRENDS | [expr expr] | 17.4.3.7 |
contains | CONTAINS | [expr expr] | 17.4.3.8 |
strbefore | STRBEFORE | [expr expr] | 17.4.3.9 |
strafter | STRAFTER | [expr expr] | 17.4.3.10 |
encode-for-uri | ENCODE_FOR_URI | [expr] | 17.4.3.11 |
concat | CONCAT | [& exprs] | 17.4.3.12 |
lang-matches | LANGMATCHES | [expr expr] | 17.4.3.13 |
regex | REGEX | [expr expr] or [expr expr expr] | 17.4.3.14 |
replace | REPLACE | [expr expr expr] or [expr expr expr expr] | 17.4.3.15 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
abs | ABS | [expr] | 17.4.4.1 |
round | ROUND | [expr] | 17.4.4.2 |
ceil | CEIL | [expr] | 17.4.4.3 |
floor | FLOOR | [expr] | 17.4.4.4 |
rand | RAND | [] | 17.4.4.5 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
now | NOW | [] | 17.4.5.1 |
year | YEAR | [expr] | 17.4.5.2 |
month | MONTH | [expr] | 17.4.5.3 |
day | DAY | [expr] | 17.4.5.4 |
hours | HOURS | [expr] | 17.4.5.5 |
minutes | MINUTES | [expr] | 17.4.5.6 |
seconds | SECONDS | [expr] | 17.4.5.7 |
timezone | TIMEZONE | [expr] | 17.4.5.8 |
tz | TZ | [expr] | 17.4.5.9 |
| Flint | SPARQL | Arglist | Reference |
|---|---|---|---|
md5 | MD5 | [expr] | 17.4.6.1 |
sha1 | SHA1 | [expr] | 17.4.6.2 |
sha256 | SHA256 | [expr] | 17.4.6.3 |
sha384 | SHA384 | [expr] | 17.4.6.4 |
sha512 | SHA512 | [expr] | 17.4.6.5 |
Aggregates are special expressions that can only be used in SELECT (and its DISTINCT and REDUCED variants), ORDER BY and HAVING clauses.
| Flint | SPARQL | Arglist |
|---|---|---|
sum | SUM | [expr & {:keys [distinct?]}] |
min | MIN | [expr & {:keys [distinct?]}] |
max | MAX | [expr & {:keys [distinct?]}] |
avg | AVG | [expr & {:keys [distinct?]}] |
sample | SAMPLE | [expr & {:keys [distinct?]}] |
count | COUNT | [expr-or-wildcard & {:keys [distinct?]}] |
group-concat | GROUP_CONCAT | [expr & {:keys [distinct? separator]}] |
The count aggregate can accept either an expression or a wildcard, e.g. both (count ?x) and (count *) are valid.
Unlike other expressions, aggregates in Flint support keyword arguments. Every aggregate function supports the :distinct? keyword arg, which accepts a boolean value. If :distinct? is true, then DISTINCT is added to the arg list in SPARQL. The example,
(sum ?x :distinct? true)
becomes
SUM(DISTINCT ?x)
group-concat also accepts the :separator keyword arg whose value is a separator string. Both :distinct? and :separator can be supported in the same expression, as so:
(group-concat ?y :distinct? true :separator ";")
which becomes
GROUP_CONCAT(DISTINCT ?y; SEPARATOR = ";")
NOTE: Using aggregates in an invalid clause, e.g. a FILTER clause, will cause a spec error.
NOTE: Using aggregates in a SELECT query, or including a GROUP BY in the query, introduces aggregate restrictions on the SELECT clause. See the SPARQL Queries page for more details.
Users can write their own custom functions, which consist of using an IRI or prefixed IRI instead of a symbol. The example:
[:filter (:func/isEven ?x)]
becomes
FILTER func:isEven(?x)
NOTE: Flint makes no attempt to validate that custom function IRIs resolve to valid resources, nor does it to attempt to validate input or output.
In :select, :order-by and :having clauses, custom aggregates are allowed, and any custom function can accept the :distinct? keyword arg. During aggregate validation, all custom functions in these clauses are treated as aggregates.
Variables can be bound to the result of expressions in :bind, :select, and :group-by clauses. In Flint, they are written in as the vector [expr var], such as in this example:
[(+ 2 2) ?four]
which then becomes:
(2 + 2) AS ?four
NOTE: In a :select or :bind clause, the variable being bound to cannot already be in-scope. In a :select clause, the var cannot be already defined in the :where clause, nor be previously projected in that same clause. In the :bind case, it cannot be already defined in previously-listed graph patterns.
Can you improve this documentation? These fine people already did:
kelvinqian00 & KelvinEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |