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 is a website building & hosting documentation for Clojure/Script libraries
× close