sparql 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -4
- data/VERSION +1 -1
- data/lib/sparql/algebra/extensions.rb +36 -0
- data/lib/sparql/algebra/operator.rb +197 -87
- data/lib/sparql/algebra/operator/abs.rb +31 -0
- data/lib/sparql/algebra/operator/base.rb +1 -0
- data/lib/sparql/algebra/operator/bnode.rb +88 -0
- data/lib/sparql/algebra/operator/bound.rb +2 -1
- data/lib/sparql/algebra/operator/ceil.rb +31 -0
- data/lib/sparql/algebra/operator/coalesce.rb +65 -0
- data/lib/sparql/algebra/operator/concat.rb +49 -0
- data/lib/sparql/algebra/operator/contains.rb +44 -0
- data/lib/sparql/algebra/operator/dataset.rb +11 -48
- data/lib/sparql/algebra/operator/datatype.rb +4 -2
- data/lib/sparql/algebra/operator/day.rb +31 -0
- data/lib/sparql/algebra/operator/encode_for_uri.rb +38 -0
- data/lib/sparql/algebra/operator/extend.rb +31 -2
- data/lib/sparql/algebra/operator/floor.rb +33 -0
- data/lib/sparql/algebra/operator/hours.rb +31 -0
- data/lib/sparql/algebra/operator/if.rb +55 -0
- data/lib/sparql/algebra/operator/in.rb +68 -0
- data/lib/sparql/algebra/operator/iri.rb +40 -0
- data/lib/sparql/algebra/operator/is_numeric.rb +41 -0
- data/lib/sparql/algebra/operator/lang_matches.rb +2 -2
- data/lib/sparql/algebra/operator/lcase.rb +31 -0
- data/lib/sparql/algebra/operator/md5.rb +34 -0
- data/lib/sparql/algebra/operator/minutes.rb +31 -0
- data/lib/sparql/algebra/operator/month.rb +31 -0
- data/lib/sparql/algebra/operator/not.rb +2 -2
- data/lib/sparql/algebra/operator/notin.rb +70 -0
- data/lib/sparql/algebra/operator/now.rb +29 -0
- data/lib/sparql/algebra/operator/order.rb +9 -13
- data/lib/sparql/algebra/operator/rand.rb +24 -0
- data/lib/sparql/algebra/operator/replace.rb +81 -0
- data/lib/sparql/algebra/operator/round.rb +31 -0
- data/lib/sparql/algebra/operator/seconds.rb +31 -0
- data/lib/sparql/algebra/operator/sha1.rb +34 -0
- data/lib/sparql/algebra/operator/sha256.rb +34 -0
- data/lib/sparql/algebra/operator/sha384.rb +34 -0
- data/lib/sparql/algebra/operator/sha512.rb +34 -0
- data/lib/sparql/algebra/operator/strafter.rb +57 -0
- data/lib/sparql/algebra/operator/strbefore.rb +59 -0
- data/lib/sparql/algebra/operator/strdt.rb +33 -0
- data/lib/sparql/algebra/operator/strends.rb +46 -0
- data/lib/sparql/algebra/operator/strlang.rb +34 -0
- data/lib/sparql/algebra/operator/strlen.rb +34 -0
- data/lib/sparql/algebra/operator/strstarts.rb +46 -0
- data/lib/sparql/algebra/operator/struuid.rb +32 -0
- data/lib/sparql/algebra/operator/substr.rb +80 -0
- data/lib/sparql/algebra/operator/timezone.rb +34 -0
- data/lib/sparql/algebra/operator/tz.rb +31 -0
- data/lib/sparql/algebra/operator/ucase.rb +31 -0
- data/lib/sparql/algebra/operator/uuid.rb +32 -0
- data/lib/sparql/algebra/operator/year.rb +31 -0
- data/lib/sparql/grammar/parser11.rb +128 -70
- data/lib/sparql/grammar/terminals11.rb +4 -5
- metadata +62 -7
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module SPARQL; module Algebra
|
4
|
+
class Operator
|
5
|
+
##
|
6
|
+
# The SPARQL logical `abs` operator.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# (encode_for_uri ?x)
|
10
|
+
#
|
11
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-encode
|
12
|
+
# @see http://www.w3.org/TR/xpath-functions/#func-abs
|
13
|
+
class EncodeForURI < Operator::Unary
|
14
|
+
include Evaluatable
|
15
|
+
|
16
|
+
NAME = :encode_for_uri
|
17
|
+
|
18
|
+
##
|
19
|
+
# The ENCODE_FOR_URI function corresponds to the XPath fn:encode-for-uri function. It returns a simple literal with the lexical form obtained from the lexical form of its input after translating reserved characters according to the fn:encode-for-uri function.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# encode_for_uri("Los Angeles") "Los%20Angeles"
|
23
|
+
# encode_for_uri("Los Angeles"@en) "Los%20Angeles"
|
24
|
+
# encode_for_uri("Los Angeles"^^xsd:string) "Los%20Angeles"
|
25
|
+
#
|
26
|
+
# @param [RDF::Literal] operand
|
27
|
+
# the operand
|
28
|
+
# @return [RDF::Literal] literal of same type
|
29
|
+
# @raise [TypeError] if the operand is not a literal value
|
30
|
+
def apply(operand)
|
31
|
+
case operand
|
32
|
+
when RDF::Literal then RDF::Literal(::URI.encode(operand.to_s))
|
33
|
+
else raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end # EncodeForURI
|
37
|
+
end # Operator
|
38
|
+
end; end # SPARQL::Algebra
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module SPARQL; module Algebra
|
2
2
|
class Operator
|
3
3
|
##
|
4
|
-
# The SPARQL
|
4
|
+
# The SPARQL `Extend` operator.
|
5
|
+
#
|
6
|
+
# Extends a solution
|
5
7
|
#
|
6
8
|
# @example
|
7
9
|
# (select (?z)
|
@@ -16,8 +18,35 @@ module SPARQL; module Algebra
|
|
16
18
|
NAME = [:extend]
|
17
19
|
|
18
20
|
##
|
19
|
-
#
|
21
|
+
# Let μ be a solution mapping, Ω a multiset of solution mappings, var a variable and expr be an expression, then we define:
|
22
|
+
#
|
23
|
+
# Extend(μ, var, expr) = μ ∪ { (var,value) | var not in dom(μ) and value = expr(μ) }
|
24
|
+
#
|
25
|
+
# Extend(μ, var, expr) = μ if var not in dom(μ) and expr(μ) is an error
|
26
|
+
#
|
27
|
+
# Extend is undefined when var in dom(μ).
|
28
|
+
#
|
29
|
+
# Extend(Ω, var, expr) = { Extend(μ, var, expr) | μ in Ω }
|
30
|
+
# @return [RDF::Query::Solutions]
|
31
|
+
# the resulting solution sequence
|
32
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#evaluation
|
20
33
|
def execute(queryable, options = {})
|
34
|
+
debug(options) {"Extend"}
|
35
|
+
@solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
|
36
|
+
@solutions.each do |solution|
|
37
|
+
debug(options) {"===> soln #{solution.to_hash.inspect}"}
|
38
|
+
operands.first.each do |(var, expr)|
|
39
|
+
begin
|
40
|
+
val = expr.evaluate(solution)
|
41
|
+
debug(options) {"===> + #{var} => #{val.inspect}"}
|
42
|
+
solution.bindings[var.to_sym] = val
|
43
|
+
rescue TypeError => e
|
44
|
+
# Evaluates to error, ignore
|
45
|
+
debug(options) {"===> #{var} error: #{e.message}"}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@solutions
|
21
50
|
end
|
22
51
|
|
23
52
|
##
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL logical `floor` operator.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# (floor ?x)
|
8
|
+
#
|
9
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-floor
|
10
|
+
# @see http://www.w3.org/TR/xpath-functions/#func-floor
|
11
|
+
class Floor < Operator::Unary
|
12
|
+
include Evaluatable
|
13
|
+
|
14
|
+
NAME = [:floor]
|
15
|
+
|
16
|
+
##
|
17
|
+
# Returns the largest (closest to positive infinity) number with no fractional part that is not greater than the value of $arg. If type of $arg is one of the four numeric types xs:float, xs:double, xs:decimal or xs:integer the type of the result is the same as the type of $arg. If the type of $arg is a type derived from one of the numeric types, the result is an instance of the base numeric type.
|
18
|
+
#
|
19
|
+
# For float and double arguments, if the argument is positive zero, then positive zero is returned. If the argument is negative zero, then negative zero is returned.
|
20
|
+
#
|
21
|
+
# @param [RDF::Literal] operand
|
22
|
+
# the operand
|
23
|
+
# @return [RDF::Literal] literal of same type
|
24
|
+
# @raise [TypeError] if the operand is not a numeric value
|
25
|
+
def apply(operand)
|
26
|
+
case operand
|
27
|
+
when RDF::Literal::Numeric then operand.floor
|
28
|
+
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end # Floor
|
32
|
+
end # Operator
|
33
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL logical `hours` operator.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# (prefix ((: <http://example.org/>))
|
8
|
+
# (project (?s ?x)
|
9
|
+
# (extend ((?x (hours ?date)))
|
10
|
+
# (bgp (triple ?s :date ?date)))))
|
11
|
+
#
|
12
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-hours
|
13
|
+
class Hours < Operator::Unary
|
14
|
+
include Evaluatable
|
15
|
+
|
16
|
+
NAME = :hours
|
17
|
+
|
18
|
+
##
|
19
|
+
# Returns the hours part of arg as an integer.
|
20
|
+
#
|
21
|
+
# @param [RDF::Literal] operand
|
22
|
+
# the operand
|
23
|
+
# @return [RDF::Literal]
|
24
|
+
# @raise [TypeError] if the operand is not a simple literal
|
25
|
+
def apply(operand)
|
26
|
+
raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
|
27
|
+
RDF::Literal(operand.object.hour)
|
28
|
+
end
|
29
|
+
end # Hours
|
30
|
+
end # Operator
|
31
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL `if` function.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# (base <http://example.org/>
|
8
|
+
# (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>))
|
9
|
+
# (project (?o ?integer)
|
10
|
+
# (extend ((?integer (if (= (lang ?o) "ja") true false)))
|
11
|
+
# (bgp (triple ?s ?p ?o))))))
|
12
|
+
#
|
13
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-if
|
14
|
+
class If < Operator::Ternary
|
15
|
+
include Evaluatable
|
16
|
+
|
17
|
+
NAME = :if
|
18
|
+
|
19
|
+
##
|
20
|
+
# The IF function form evaluates the first argument, interprets it as a effective boolean value, then returns the value of expression2 if the EBV is true, otherwise it returns the value of expression3. Only one of expression2 and expression3 is evaluated. If evaluating the first argument raises an error, then an error is raised for the evaluation of the IF expression.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
#
|
24
|
+
# IF(?x = 2, "yes", "no") #=> "yes"
|
25
|
+
# IF(bound(?y), "yes", "no") #=> "no"
|
26
|
+
# IF(?x=2, "yes", 1/?z) #=> "yes", the expression 1/?z is not evaluated
|
27
|
+
# IF(?x=1, "yes", 1/?z) #=> raises an error
|
28
|
+
# IF("2" > 1, "yes", "no") #=> raises an error
|
29
|
+
#
|
30
|
+
# Evaluates the first operand and returns the evaluation of either the second or third operands
|
31
|
+
#
|
32
|
+
# @param [RDF::Query::Solution, #[]] bindings
|
33
|
+
# a query solution containing zero or more variable bindings
|
34
|
+
# @return [RDF::Term]
|
35
|
+
# @raise [TypeError]
|
36
|
+
def evaluate(bindings = {})
|
37
|
+
operand(0).evaluate(bindings) == RDF::Literal::TRUE ?
|
38
|
+
operand(1).evaluate(bindings) :
|
39
|
+
operand(2).evaluate(bindings)
|
40
|
+
rescue
|
41
|
+
raise TypeError
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Returns an optimized version of this query.
|
46
|
+
#
|
47
|
+
# Return optimized query
|
48
|
+
#
|
49
|
+
# @return [Union, RDF::Query] `self`
|
50
|
+
def optimize
|
51
|
+
operands = operands.map(&:optimize)
|
52
|
+
end
|
53
|
+
end # If
|
54
|
+
end # Operator
|
55
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL GraphPattern `in` operator.
|
5
|
+
#
|
6
|
+
# Used for filters with more than one expression.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# (ask (filter (in 2 1 2 3) (bgp)))
|
10
|
+
#
|
11
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-in
|
12
|
+
class In < Operator
|
13
|
+
include Evaluatable
|
14
|
+
|
15
|
+
NAME = :in
|
16
|
+
|
17
|
+
##
|
18
|
+
# The IN operator tests whether the RDF term on the left-hand side is found in the values of list of expressions on the right-hand side. The test is done with "=" operator, which tests for the same value, as determined by the operator mapping.
|
19
|
+
#
|
20
|
+
# A list of zero terms on the right-hand side is legal.
|
21
|
+
#
|
22
|
+
# Errors in comparisons cause the IN expression to raise an error if the RDF term being tested is not found elsewhere in the list of terms.
|
23
|
+
#
|
24
|
+
# The IN operator is equivalent to the SPARQL expression:
|
25
|
+
#
|
26
|
+
# (lhs = expression1) || (lhs = expression2) || ...
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
#
|
30
|
+
# 2 IN (1, 2, 3) #=> true
|
31
|
+
# 2 IN () #=> false
|
32
|
+
# 2 IN (<http://example/iri>, "str", 2.0) #=> true
|
33
|
+
# 2 IN (1/0, 2) #=> true
|
34
|
+
# 2 IN (2, 1/0) #=> true
|
35
|
+
# 2 IN (3, 1/0) #=> raises an error
|
36
|
+
#
|
37
|
+
# @param [RDF::Query::Solution, #[]] bindings
|
38
|
+
# @return [RDF::Literal::Boolean] `true` or `false`
|
39
|
+
# @raise [TypeError] if term is not found and any operand raises an error
|
40
|
+
def evaluate(bindings = {})
|
41
|
+
lhs = operands.shift.evaluate(bindings)
|
42
|
+
error_found = false
|
43
|
+
found = operands.any? do |op|
|
44
|
+
begin
|
45
|
+
lhs == op.evaluate(bindings)
|
46
|
+
rescue TypeError
|
47
|
+
error_found = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
case
|
51
|
+
when found then RDF::Literal::TRUE
|
52
|
+
when error_found then raise TypeError
|
53
|
+
else RDF::Literal::FALSE
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Returns an optimized version of this query.
|
59
|
+
#
|
60
|
+
# Return optimized query
|
61
|
+
#
|
62
|
+
# @return [Union, RDF::Query] `self`
|
63
|
+
def optimize
|
64
|
+
operands = operands.map(&:optimize)
|
65
|
+
end
|
66
|
+
end # In
|
67
|
+
end # Operator
|
68
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL `iri` operator.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# (base <http://example.org/> (project (?uri ?iri)
|
8
|
+
# (extend ((?uri (uri "uri")) (?iri (iri "iri")))
|
9
|
+
# (bgp))))
|
10
|
+
#
|
11
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-iri
|
12
|
+
class IRI < Operator::Unary
|
13
|
+
include Evaluatable
|
14
|
+
|
15
|
+
NAME = [:iri, :uri]
|
16
|
+
|
17
|
+
##
|
18
|
+
# The IRI function constructs an IRI by resolving the string argument (see RFC 3986 and RFC 3987 or any later RFC that superceeds RFC 3986 or RFC 3987). The IRI is resolved against the base IRI of the query and must result in an absolute IRI.
|
19
|
+
#
|
20
|
+
# The URI function is a synonym for IRI.
|
21
|
+
#
|
22
|
+
# If the function is passed an IRI, it returns the IRI unchanged.
|
23
|
+
#
|
24
|
+
# Passing any RDF term other than a simple literal, xsd:string or an IRI is an error.
|
25
|
+
#
|
26
|
+
# An implementation may normalize the IRI.
|
27
|
+
#
|
28
|
+
# @param [RDF::Term] literal
|
29
|
+
# a simple literal
|
30
|
+
# @return [RDF::URI]
|
31
|
+
# @raise [TypeError] if the operand is not a simple literal
|
32
|
+
def apply(literal)
|
33
|
+
raise TypeError, "expected an simple literal, but got #{literal.inspect}" unless literal.literal? && literal.simple?
|
34
|
+
Operator.base_uri.join(literal.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
Operator::URI = IRI
|
38
|
+
end # IRI
|
39
|
+
end # Operator
|
40
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL `isNumeric` operator.
|
5
|
+
#
|
6
|
+
# Note numeric denotes typed literals with datatypes xsd:integer, xsd:decimal, xsd:float, and xsd:double, not derived types.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
|
10
|
+
# (: <http://example.org/things#>))
|
11
|
+
# (project (?x ?v)
|
12
|
+
# (filter (isNumeric ?v)
|
13
|
+
# (bgp (triple ?x :p ?v)))))
|
14
|
+
#
|
15
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-isNumeric
|
16
|
+
class IsNumeric < Operator::Unary
|
17
|
+
include Evaluatable
|
18
|
+
|
19
|
+
NAME = :isnumeric
|
20
|
+
|
21
|
+
##
|
22
|
+
# Returns `true` if the operand is an `RDF::Literal::Numeric`, `false`
|
23
|
+
# otherwise.
|
24
|
+
#
|
25
|
+
# @param [RDF::Term] term
|
26
|
+
# an RDF term
|
27
|
+
# @return [RDF::Literal::Boolean] `true` or `false`
|
28
|
+
# @raise [TypeError] if the operand is not an RDF term
|
29
|
+
def apply(term)
|
30
|
+
case term
|
31
|
+
when RDF::Literal::NonPositiveInteger then RDF::Literal::FALSE
|
32
|
+
when RDF::Literal::NonNegativeInteger then RDF::Literal::FALSE
|
33
|
+
when RDF::Literal::Long then RDF::Literal::FALSE
|
34
|
+
when RDF::Literal::Numeric then RDF::Literal::TRUE
|
35
|
+
when RDF::Term then RDF::Literal::FALSE
|
36
|
+
else raise TypeError, "expected an RDF::Term, but got #{term.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end # IsNumeric
|
40
|
+
end # Operator
|
41
|
+
end; end # SPARQL::Algebra
|
@@ -28,10 +28,10 @@ module SPARQL; module Algebra
|
|
28
28
|
# @raise [TypeError] if either operand is unbound
|
29
29
|
# @raise [TypeError] if either operand is not a simple literal
|
30
30
|
def apply(language_tag, language_range)
|
31
|
-
raise TypeError, "expected a plain RDF::Literal for language_tag, but got #{language_tag.inspect}" unless language_tag.is_a?(RDF::Literal) && language_tag.
|
31
|
+
raise TypeError, "expected a plain RDF::Literal for language_tag, but got #{language_tag.inspect}" unless language_tag.is_a?(RDF::Literal) && language_tag.simple?
|
32
32
|
language_tag = language_tag.to_s.downcase
|
33
33
|
|
34
|
-
raise TypeError, "expected a plain RDF::Literal for language_range, but got #{language_range.inspect}" unless language_range.is_a?(RDF::Literal) && language_range.
|
34
|
+
raise TypeError, "expected a plain RDF::Literal for language_range, but got #{language_range.inspect}" unless language_range.is_a?(RDF::Literal) && language_range.simple?
|
35
35
|
language_range = language_range.to_s.downcase
|
36
36
|
|
37
37
|
case
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL logical `lcase` operator.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# (lcase ?x)
|
8
|
+
#
|
9
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-lcase
|
10
|
+
# @see http://www.w3.org/TR/xpath-functions/#func-lcase
|
11
|
+
class LCase < Operator::Unary
|
12
|
+
include Evaluatable
|
13
|
+
|
14
|
+
NAME = :lcase
|
15
|
+
|
16
|
+
##
|
17
|
+
# The LCASE function corresponds to the XPath fn:lower-case function. It returns a string literal whose lexical form is the lower case of the lexcial form of the argument.
|
18
|
+
#
|
19
|
+
# @param [RDF::Literal] operand
|
20
|
+
# the operand
|
21
|
+
# @return [RDF::Literal] literal of same type
|
22
|
+
# @raise [TypeError] if the operand is not a literal value
|
23
|
+
def apply(operand)
|
24
|
+
case operand
|
25
|
+
when RDF::Literal then RDF::Literal(operand.to_s.downcase, :datatype => operand.datatype, :language => operand.language)
|
26
|
+
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end # LCase
|
30
|
+
end # Operator
|
31
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module SPARQL; module Algebra
|
4
|
+
class Operator
|
5
|
+
##
|
6
|
+
# The SPARQL logical `md5` operator.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# (prefix ((: <http://example.org/>))
|
10
|
+
# (project (?hash)
|
11
|
+
# (extend ((?hash (md5 ?l)))
|
12
|
+
# (bgp (triple :s1 :str ?l)))))
|
13
|
+
#
|
14
|
+
# @see http://www.w3.org/TR/sparql11-query/#func-md5
|
15
|
+
class MD5 < Operator::Unary
|
16
|
+
include Evaluatable
|
17
|
+
|
18
|
+
NAME = :md5
|
19
|
+
|
20
|
+
##
|
21
|
+
# Returns the MD5 checksum, as a hex digit string, calculated on the UTF-8 representation of the simple literal or lexical form of the xsd:string. Hex digits should be in lower case.
|
22
|
+
#
|
23
|
+
# @param [RDF::Literal] operand
|
24
|
+
# the operand
|
25
|
+
# @return [RDF::Literal]
|
26
|
+
# @raise [TypeError] if the operand is not a simple literal
|
27
|
+
def apply(operand)
|
28
|
+
raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}" unless operand.literal?
|
29
|
+
raise TypeError, "expected simple literal or xsd:string, but got #{operand.inspect}" unless (operand.datatype || RDF::XSD.string) == RDF::XSD.string
|
30
|
+
RDF::Literal(Digest::MD5.new.hexdigest(operand.to_s))
|
31
|
+
end
|
32
|
+
end # MD5
|
33
|
+
end # Operator
|
34
|
+
end; end # SPARQL::Algebra
|