sparql 3.0.2 → 3.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +189 -74
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/bin/sparql +44 -24
- data/lib/rack/sparql.rb +1 -1
- data/lib/rack/sparql/conneg.rb +3 -3
- data/lib/sinatra/sparql.rb +5 -5
- data/lib/sparql.rb +17 -16
- data/lib/sparql/algebra.rb +15 -23
- data/lib/sparql/algebra/aggregate.rb +4 -4
- data/lib/sparql/algebra/evaluatable.rb +2 -2
- data/lib/sparql/algebra/expression.rb +70 -44
- data/lib/sparql/algebra/extensions.rb +181 -34
- data/lib/sparql/algebra/operator.rb +44 -23
- data/lib/sparql/algebra/operator/abs.rb +2 -2
- data/lib/sparql/algebra/operator/add.rb +3 -3
- data/lib/sparql/algebra/operator/alt.rb +4 -4
- data/lib/sparql/algebra/operator/and.rb +7 -7
- data/lib/sparql/algebra/operator/asc.rb +3 -3
- data/lib/sparql/algebra/operator/ask.rb +4 -14
- data/lib/sparql/algebra/operator/avg.rb +13 -4
- data/lib/sparql/algebra/operator/base.rb +10 -10
- data/lib/sparql/algebra/operator/bgp.rb +2 -2
- data/lib/sparql/algebra/operator/bnode.rb +5 -5
- data/lib/sparql/algebra/operator/bound.rb +3 -3
- data/lib/sparql/algebra/operator/ceil.rb +2 -2
- data/lib/sparql/algebra/operator/clear.rb +3 -3
- data/lib/sparql/algebra/operator/coalesce.rb +3 -13
- data/lib/sparql/algebra/operator/compare.rb +8 -8
- data/lib/sparql/algebra/operator/concat.rb +4 -4
- data/lib/sparql/algebra/operator/construct.rb +4 -14
- data/lib/sparql/algebra/operator/contains.rb +2 -2
- data/lib/sparql/algebra/operator/copy.rb +3 -3
- data/lib/sparql/algebra/operator/count.rb +3 -3
- data/lib/sparql/algebra/operator/create.rb +3 -3
- data/lib/sparql/algebra/operator/dataset.rb +6 -17
- data/lib/sparql/algebra/operator/datatype.rb +1 -1
- data/lib/sparql/algebra/operator/day.rb +1 -1
- data/lib/sparql/algebra/operator/delete.rb +9 -7
- data/lib/sparql/algebra/operator/delete_data.rb +3 -3
- data/lib/sparql/algebra/operator/delete_where.rb +6 -6
- data/lib/sparql/algebra/operator/desc.rb +1 -1
- data/lib/sparql/algebra/operator/describe.rb +3 -13
- data/lib/sparql/algebra/operator/distinct.rb +4 -14
- data/lib/sparql/algebra/operator/divide.rb +1 -1
- data/lib/sparql/algebra/operator/drop.rb +3 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +3 -3
- data/lib/sparql/algebra/operator/equal.rb +2 -2
- data/lib/sparql/algebra/operator/exists.rb +5 -5
- data/lib/sparql/algebra/operator/exprlist.rb +3 -13
- data/lib/sparql/algebra/operator/extend.rb +19 -18
- data/lib/sparql/algebra/operator/filter.rb +6 -16
- data/lib/sparql/algebra/operator/floor.rb +2 -2
- data/lib/sparql/algebra/operator/graph.rb +6 -17
- data/lib/sparql/algebra/operator/greater_than.rb +5 -5
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/group.rb +25 -25
- data/lib/sparql/algebra/operator/group_concat.rb +6 -6
- data/lib/sparql/algebra/operator/hours.rb +1 -1
- data/lib/sparql/algebra/operator/if.rb +5 -15
- data/lib/sparql/algebra/operator/in.rb +4 -14
- data/lib/sparql/algebra/operator/insert.rb +7 -5
- data/lib/sparql/algebra/operator/insert_data.rb +3 -3
- data/lib/sparql/algebra/operator/iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_blank.rb +1 -1
- data/lib/sparql/algebra/operator/is_iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_literal.rb +1 -1
- data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
- data/lib/sparql/algebra/operator/join.rb +12 -10
- data/lib/sparql/algebra/operator/lang.rb +1 -1
- data/lib/sparql/algebra/operator/lang_matches.rb +3 -3
- data/lib/sparql/algebra/operator/lcase.rb +2 -2
- data/lib/sparql/algebra/operator/left_join.rb +19 -12
- data/lib/sparql/algebra/operator/less_than.rb +5 -5
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/load.rb +3 -3
- data/lib/sparql/algebra/operator/max.rb +13 -4
- data/lib/sparql/algebra/operator/md5.rb +1 -1
- data/lib/sparql/algebra/operator/min.rb +13 -4
- data/lib/sparql/algebra/operator/minus.rb +12 -11
- data/lib/sparql/algebra/operator/minutes.rb +1 -1
- data/lib/sparql/algebra/operator/modify.rb +4 -4
- data/lib/sparql/algebra/operator/month.rb +1 -1
- data/lib/sparql/algebra/operator/move.rb +3 -3
- data/lib/sparql/algebra/operator/multiply.rb +1 -1
- data/lib/sparql/algebra/operator/negate.rb +1 -1
- data/lib/sparql/algebra/operator/not.rb +1 -1
- data/lib/sparql/algebra/operator/not_equal.rb +2 -2
- data/lib/sparql/algebra/operator/notexists.rb +4 -4
- data/lib/sparql/algebra/operator/notin.rb +4 -14
- data/lib/sparql/algebra/operator/notoneof.rb +5 -6
- data/lib/sparql/algebra/operator/now.rb +1 -1
- data/lib/sparql/algebra/operator/or.rb +7 -7
- data/lib/sparql/algebra/operator/order.rb +6 -16
- data/lib/sparql/algebra/operator/path.rb +6 -5
- data/lib/sparql/algebra/operator/path_opt.rb +16 -16
- data/lib/sparql/algebra/operator/path_plus.rb +8 -8
- data/lib/sparql/algebra/operator/path_star.rb +4 -4
- data/lib/sparql/algebra/operator/plus.rb +3 -3
- data/lib/sparql/algebra/operator/prefix.rb +10 -10
- data/lib/sparql/algebra/operator/project.rb +4 -14
- data/lib/sparql/algebra/operator/rand.rb +1 -1
- data/lib/sparql/algebra/operator/reduced.rb +4 -14
- data/lib/sparql/algebra/operator/regex.rb +6 -6
- data/lib/sparql/algebra/operator/replace.rb +4 -4
- data/lib/sparql/algebra/operator/reverse.rb +4 -4
- data/lib/sparql/algebra/operator/round.rb +2 -2
- data/lib/sparql/algebra/operator/same_term.rb +8 -5
- data/lib/sparql/algebra/operator/sample.rb +11 -4
- data/lib/sparql/algebra/operator/seconds.rb +1 -1
- data/lib/sparql/algebra/operator/seq.rb +5 -6
- data/lib/sparql/algebra/operator/sequence.rb +4 -4
- data/lib/sparql/algebra/operator/sha1.rb +1 -1
- data/lib/sparql/algebra/operator/sha256.rb +1 -1
- data/lib/sparql/algebra/operator/sha384.rb +1 -1
- data/lib/sparql/algebra/operator/sha512.rb +1 -1
- data/lib/sparql/algebra/operator/slice.rb +4 -14
- data/lib/sparql/algebra/operator/str.rb +1 -1
- data/lib/sparql/algebra/operator/strafter.rb +2 -2
- data/lib/sparql/algebra/operator/strbefore.rb +2 -2
- data/lib/sparql/algebra/operator/strdt.rb +2 -2
- data/lib/sparql/algebra/operator/strends.rb +2 -2
- data/lib/sparql/algebra/operator/strlang.rb +2 -2
- data/lib/sparql/algebra/operator/strlen.rb +2 -2
- data/lib/sparql/algebra/operator/strstarts.rb +2 -2
- data/lib/sparql/algebra/operator/struuid.rb +1 -1
- data/lib/sparql/algebra/operator/substr.rb +4 -4
- data/lib/sparql/algebra/operator/subtract.rb +1 -1
- data/lib/sparql/algebra/operator/sum.rb +6 -4
- data/lib/sparql/algebra/operator/table.rb +3 -3
- data/lib/sparql/algebra/operator/timezone.rb +1 -1
- data/lib/sparql/algebra/operator/tz.rb +1 -1
- data/lib/sparql/algebra/operator/ucase.rb +2 -2
- data/lib/sparql/algebra/operator/union.rb +9 -8
- data/lib/sparql/algebra/operator/update.rb +4 -4
- data/lib/sparql/algebra/operator/using.rb +4 -4
- data/lib/sparql/algebra/operator/uuid.rb +1 -1
- data/lib/sparql/algebra/operator/with.rb +7 -7
- data/lib/sparql/algebra/operator/year.rb +1 -1
- data/lib/sparql/algebra/query.rb +2 -2
- data/lib/sparql/algebra/update.rb +2 -2
- data/lib/sparql/algebra/version.rb +1 -1
- data/lib/sparql/extensions.rb +11 -17
- data/lib/sparql/grammar.rb +113 -13
- data/lib/sparql/grammar/meta.rb +2340 -907
- data/lib/sparql/grammar/parser11.rb +57 -52
- data/lib/sparql/grammar/terminals11.rb +2 -0
- data/lib/sparql/results.rb +73 -46
- data/lib/sparql/version.rb +1 -1
- metadata +46 -63
@@ -6,8 +6,8 @@ module SPARQL::Grammar
|
|
6
6
|
##
|
7
7
|
# A parser for the SPARQL 1.1 grammar.
|
8
8
|
#
|
9
|
-
# @see
|
10
|
-
# @see
|
9
|
+
# @see https://www.w3.org/TR/sparql11-query/#grammar
|
10
|
+
# @see https://en.wikipedia.org/wiki/LR_parser
|
11
11
|
class Parser
|
12
12
|
include SPARQL::Grammar::Meta
|
13
13
|
include SPARQL::Grammar::Terminals
|
@@ -586,7 +586,7 @@ module SPARQL::Grammar
|
|
586
586
|
production(:GroupGraphPatternSub) do |input, data, callback|
|
587
587
|
debug("GroupGraphPatternSub") {"q #{data[:query].inspect}"}
|
588
588
|
|
589
|
-
res = case data[:query].length
|
589
|
+
res = case Array(data[:query]).length
|
590
590
|
when 0 then SPARQL::Algebra::Operator::BGP.new
|
591
591
|
when 1 then data[:query].first
|
592
592
|
when 2
|
@@ -701,9 +701,9 @@ module SPARQL::Grammar
|
|
701
701
|
end
|
702
702
|
end
|
703
703
|
|
704
|
-
# [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
|
704
|
+
# [60] Bind ::= 'BIND' '(' (Expression || EmbTP) 'AS' Var ')'
|
705
705
|
production(:Bind) do |input, data, callback|
|
706
|
-
add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
|
706
|
+
add_prod_datum :extend, [(data[:Expression] || data[:pattern]).unshift(data[:Var].first)]
|
707
707
|
end
|
708
708
|
|
709
709
|
# [61] InlineData ::= 'VALUES' DataBlock
|
@@ -867,13 +867,21 @@ module SPARQL::Grammar
|
|
867
867
|
add_prod_datum(:path, data[:path])
|
868
868
|
end
|
869
869
|
|
870
|
-
# [
|
870
|
+
# [177] AnnotationPattern ::= '{|' PropertyListNotEmpty '|}'
|
871
|
+
start_production(:AnnotationPattern) do |input, data, callback|
|
872
|
+
data[:TriplesNode] = prod_data[:pattern].first
|
873
|
+
end
|
874
|
+
production(:AnnotationPattern) do |input, data, callback|
|
875
|
+
add_prod_datum(:pattern, data[:pattern])
|
876
|
+
end
|
877
|
+
|
878
|
+
# [80] Object ::= GraphNode | EmbTP
|
871
879
|
production(:Object) do |input, data, callback|
|
872
|
-
object = data[:
|
880
|
+
object = data[:GraphNode] || data[:EmbTP]
|
881
|
+
add_prod_datum(:pattern, data[:pattern])
|
873
882
|
if object
|
874
883
|
if prod_data[:Verb]
|
875
884
|
add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
|
876
|
-
add_prod_datum(:pattern, data[:pattern])
|
877
885
|
elsif prod_data[:VerbPath]
|
878
886
|
add_prod_datum(:path,
|
879
887
|
SPARQL::Algebra::Expression(:path,
|
@@ -1104,6 +1112,11 @@ module SPARQL::Grammar
|
|
1104
1112
|
data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
|
1105
1113
|
end
|
1106
1114
|
|
1115
|
+
# [106s] VarOrTermOrEmbTP ::= Var | GraphTerm | EmbTP
|
1116
|
+
production(:VarOrTermOrEmbTP) do |input, data, callback|
|
1117
|
+
data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
|
1118
|
+
end
|
1119
|
+
|
1107
1120
|
# [107] VarOrIri ::= Var | iri
|
1108
1121
|
production(:VarOrIri) do |input, data, callback|
|
1109
1122
|
data.values.each {|v| add_prod_datum(:VarOrIri, v)}
|
@@ -1119,6 +1132,22 @@ module SPARQL::Grammar
|
|
1119
1132
|
data[:NIL])
|
1120
1133
|
end
|
1121
1134
|
|
1135
|
+
# [174] EmbTP ::= '<<' EmbSubjectOrObject Verb EmbSubjectOrObject '>>'
|
1136
|
+
production(:EmbTP) do |input, data, callback|
|
1137
|
+
subject, object = data[:EmbSubjectOrObject]
|
1138
|
+
predicate = data[:Verb]
|
1139
|
+
add_pattern(:EmbTP,
|
1140
|
+
subject: subject,
|
1141
|
+
predicate: predicate,
|
1142
|
+
object: object)
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
# [175] EmbSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
|
1146
|
+
# | NumericLiteral | BooleanLiteral | EmbTP
|
1147
|
+
production(:EmbSubjectOrObject) do |input, data, callback|
|
1148
|
+
data.values.each {|v| add_prod_datum(:EmbSubjectOrObject, v)}
|
1149
|
+
end
|
1150
|
+
|
1122
1151
|
# [110] Expression ::= ConditionalOrExpression
|
1123
1152
|
production(:Expression) do |input, data, callback|
|
1124
1153
|
add_prod_datum(:Expression, data[:Expression])
|
@@ -1415,7 +1444,7 @@ module SPARQL::Grammar
|
|
1415
1444
|
str = lit.delete(:string)
|
1416
1445
|
lit[:datatype] = lit.delete(:iri) if lit[:iri]
|
1417
1446
|
lit[:language] = lit.delete(:language).last.downcase if lit[:language]
|
1418
|
-
input[:literal] = RDF::Literal.new(str, lit) if str
|
1447
|
+
input[:literal] = RDF::Literal.new(str, **lit) if str
|
1419
1448
|
end
|
1420
1449
|
end
|
1421
1450
|
|
@@ -1458,25 +1487,19 @@ module SPARQL::Grammar
|
|
1458
1487
|
# definitions.
|
1459
1488
|
# @option options [Boolean] :validate (false)
|
1460
1489
|
# whether to validate the parsed statements and values
|
1461
|
-
# @option options [
|
1462
|
-
#
|
1463
|
-
# @option options [Boolean] :debug
|
1464
|
-
# Detailed debug output
|
1490
|
+
# @option options [Logger, #write, #<<] :logger
|
1491
|
+
# Record error/info/debug output
|
1465
1492
|
# @yield [parser] `self`
|
1466
1493
|
# @yieldparam [SPARQL::Grammar::Parser] parser
|
1467
1494
|
# @yieldreturn [void] ignored
|
1468
1495
|
# @return [SPARQL::Grammar::Parser]
|
1469
|
-
def initialize(input = nil, options
|
1496
|
+
def initialize(input = nil, **options, &block)
|
1470
1497
|
@input = case input
|
1471
1498
|
when IO, StringIO then input.read
|
1472
1499
|
else input.to_s.dup
|
1473
1500
|
end
|
1474
1501
|
@input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
|
1475
1502
|
@options = {anon_base: "b0", validate: false}.merge(options)
|
1476
|
-
@options[:debug] ||= case
|
1477
|
-
when options[:progress] then 2
|
1478
|
-
when options[:validate] then 1
|
1479
|
-
end
|
1480
1503
|
|
1481
1504
|
debug("base IRI") {base_uri.inspect}
|
1482
1505
|
debug("validate") {validate?.inspect}
|
@@ -1527,30 +1550,17 @@ module SPARQL::Grammar
|
|
1527
1550
|
# @param [Symbol, #to_s] prod The starting production for the parser.
|
1528
1551
|
# It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
|
1529
1552
|
# @return [Array]
|
1530
|
-
# @see
|
1531
|
-
# @see
|
1553
|
+
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
1554
|
+
# @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
|
1532
1555
|
def parse(prod = START)
|
1533
|
-
ll1_parse(@input,
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
message = args.to_sse
|
1542
|
-
d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
|
1543
|
-
str = "[#{lineno}](#{level})#{d_str}#{message}".chop
|
1544
|
-
case @options[:debug]
|
1545
|
-
when Array
|
1546
|
-
@options[:debug] << str unless level > 2
|
1547
|
-
when TrueClass
|
1548
|
-
$stderr.puts str
|
1549
|
-
when Integer
|
1550
|
-
$stderr.puts(str) if level <= @options[:debug]
|
1551
|
-
end
|
1552
|
-
end
|
1553
|
-
end
|
1556
|
+
ll1_parse(@input,
|
1557
|
+
prod.to_sym,
|
1558
|
+
branch: BRANCH,
|
1559
|
+
first: FIRST,
|
1560
|
+
follow: FOLLOW,
|
1561
|
+
whitespace: WS,
|
1562
|
+
**@options
|
1563
|
+
)
|
1554
1564
|
|
1555
1565
|
# The last thing on the @prod_data stack is the result
|
1556
1566
|
@result = case
|
@@ -1718,9 +1728,7 @@ module SPARQL::Grammar
|
|
1718
1728
|
|
1719
1729
|
if id
|
1720
1730
|
@vars[id] ||= begin
|
1721
|
-
|
1722
|
-
v.distinguished = distinguished
|
1723
|
-
v
|
1731
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1724
1732
|
end
|
1725
1733
|
else
|
1726
1734
|
unless distinguished
|
@@ -1728,9 +1736,7 @@ module SPARQL::Grammar
|
|
1728
1736
|
id = @nd_var_gen
|
1729
1737
|
@nd_var_gen = id.succ
|
1730
1738
|
end
|
1731
|
-
|
1732
|
-
v.distinguished = distinguished
|
1733
|
-
v
|
1739
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1734
1740
|
end
|
1735
1741
|
end
|
1736
1742
|
|
@@ -1758,7 +1764,7 @@ module SPARQL::Grammar
|
|
1758
1764
|
end
|
1759
1765
|
|
1760
1766
|
# Create a literal
|
1761
|
-
def literal(value, options
|
1767
|
+
def literal(value, **options)
|
1762
1768
|
options = options.dup
|
1763
1769
|
# Internal representation is to not use xsd:string, although it could arguably go the other way.
|
1764
1770
|
options.delete(:datatype) if options[:datatype] == RDF::XSD.string
|
@@ -1767,7 +1773,7 @@ module SPARQL::Grammar
|
|
1767
1773
|
"options: #{options.inspect}, " +
|
1768
1774
|
"validate: #{validate?.inspect}, "
|
1769
1775
|
end
|
1770
|
-
RDF::Literal.new(value,
|
1776
|
+
RDF::Literal.new(value, validate: validate?, **options)
|
1771
1777
|
end
|
1772
1778
|
|
1773
1779
|
# Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
|
@@ -1798,7 +1804,7 @@ module SPARQL::Grammar
|
|
1798
1804
|
#
|
1799
1805
|
# @param [String] production Production generating pattern
|
1800
1806
|
# @param [Hash{Symbol => Object}] options
|
1801
|
-
def add_pattern(production, options)
|
1807
|
+
def add_pattern(production, **options)
|
1802
1808
|
progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
|
1803
1809
|
triple = {}
|
1804
1810
|
options.each_pair do |r, v|
|
@@ -1880,8 +1886,7 @@ module SPARQL::Grammar
|
|
1880
1886
|
avf.first
|
1881
1887
|
else
|
1882
1888
|
# Allocate a temporary variable for this function, and retain the mapping for outside the group
|
1883
|
-
av = RDF::Query::Variable.new(".#{agg}")
|
1884
|
-
av.distinguished = false
|
1889
|
+
av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
|
1885
1890
|
agg += 1
|
1886
1891
|
aggregates << [av, function]
|
1887
1892
|
av
|
data/lib/sparql/results.rb
CHANGED
@@ -14,28 +14,38 @@ module SPARQL
|
|
14
14
|
##
|
15
15
|
# Generate Solutions as JSON
|
16
16
|
# @return [String]
|
17
|
-
# @see
|
17
|
+
# @see https://www.w3.org/TR/rdf-sparql-json-res/
|
18
18
|
def to_json
|
19
19
|
require 'json' unless defined?(::JSON)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
{
|
28
|
-
|
29
|
-
|
30
|
-
{n => {type: "typed-literal", datatype: s.datatype.to_s, value: s.to_s }}
|
31
|
-
elsif s.language
|
32
|
-
{n => {type: "literal", "xml:lang" => s.language.to_s, value: s.to_s }}
|
33
|
-
else
|
34
|
-
{n => {type: "literal", value: s.to_s }}
|
35
|
-
end
|
20
|
+
|
21
|
+
format = ->(value) do
|
22
|
+
case value
|
23
|
+
when RDF::URI then {type: "uri", value: value.to_s }
|
24
|
+
when RDF::Node then {type: "bnode", value: value.id }
|
25
|
+
when RDF::Literal
|
26
|
+
if value.datatype?
|
27
|
+
{type: "typed-literal", datatype: value.datatype.to_s, value: value.to_s }
|
28
|
+
elsif value.language?
|
29
|
+
{type: "literal", "xml:lang" => value.language.to_s, value: value.to_s }
|
36
30
|
else
|
37
|
-
{}
|
31
|
+
{type: "literal", value: value.to_s }
|
38
32
|
end
|
33
|
+
when RDF::Statement
|
34
|
+
{
|
35
|
+
type: 'triple',
|
36
|
+
value: {
|
37
|
+
subject: format.call(value.subject),
|
38
|
+
predicate: format.call(value.predicate),
|
39
|
+
object: format.call(value.object)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
bindings = self.map do |solution|
|
46
|
+
variable_names.inject({}) do |memo, n|
|
47
|
+
rep = format.call(solution[n])
|
48
|
+
rep ? memo.merge(n => rep) : memo
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
@@ -48,12 +58,36 @@ module SPARQL
|
|
48
58
|
##
|
49
59
|
# Generate Solutions as XML
|
50
60
|
# @return [String]
|
51
|
-
# @see
|
61
|
+
# @see https://www.w3.org/TR/rdf-sparql-XMLres/
|
52
62
|
def to_xml
|
53
63
|
require 'builder' unless defined?(::Builder)
|
54
64
|
|
55
65
|
xml = ::Builder::XmlMarkup.new(indent: 2)
|
56
66
|
xml.instruct!
|
67
|
+
|
68
|
+
format = ->(s) do
|
69
|
+
case s
|
70
|
+
when RDF::URI
|
71
|
+
xml.uri(s.to_s)
|
72
|
+
when RDF::Node
|
73
|
+
xml.bnode(s.id)
|
74
|
+
when RDF::Literal
|
75
|
+
if s.datatype?
|
76
|
+
xml.literal(s.to_s, "datatype" => s.datatype.to_s)
|
77
|
+
elsif s.language
|
78
|
+
xml.literal(s.to_s, "xml:lang" => s.language.to_s)
|
79
|
+
else
|
80
|
+
xml.literal(s.to_s)
|
81
|
+
end
|
82
|
+
when RDF::Statement
|
83
|
+
xml.triple do
|
84
|
+
xml.subject {format.call(s.subject)}
|
85
|
+
xml.predicate {format.call(s.predicate)}
|
86
|
+
xml.object {format.call(s.object)}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
57
91
|
xml.sparql(xmlns: "http://www.w3.org/2005/sparql-results#") do
|
58
92
|
xml.head do
|
59
93
|
variable_names.each do |n|
|
@@ -67,20 +101,7 @@ module SPARQL
|
|
67
101
|
s = solution[n]
|
68
102
|
next unless s
|
69
103
|
xml.binding(name: n) do
|
70
|
-
|
71
|
-
when RDF::URI
|
72
|
-
xml.uri(s.to_s)
|
73
|
-
when RDF::Node
|
74
|
-
xml.bnode(s.id)
|
75
|
-
when RDF::Literal
|
76
|
-
if s.datatype?
|
77
|
-
xml.literal(s.to_s, "datatype" => s.datatype.to_s)
|
78
|
-
elsif s.language
|
79
|
-
xml.literal(s.to_s, "xml:lang" => s.language.to_s)
|
80
|
-
else
|
81
|
-
xml.literal(s.to_s)
|
82
|
-
end
|
83
|
-
end
|
104
|
+
format.call(s)
|
84
105
|
end
|
85
106
|
end
|
86
107
|
end
|
@@ -118,10 +139,9 @@ module SPARQL
|
|
118
139
|
##
|
119
140
|
# Generate Solutions as CSV
|
120
141
|
# @return [String]
|
121
|
-
# @see
|
122
|
-
def to_csv
|
142
|
+
# @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
|
143
|
+
def to_csv(bnode_map: {})
|
123
144
|
require 'csv' unless defined?(::CSV)
|
124
|
-
bnode_map = {}
|
125
145
|
bnode_gen = "_:a"
|
126
146
|
CSV.generate(row_sep: "\r\n") do |csv|
|
127
147
|
csv << variable_names.to_a
|
@@ -134,8 +154,12 @@ module SPARQL
|
|
134
154
|
bnode_gen = bnode_gen.succ
|
135
155
|
this
|
136
156
|
end
|
157
|
+
when RDF::Statement
|
158
|
+
RDF::Query::Solutions(
|
159
|
+
RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
|
160
|
+
).to_csv(bnode_map: bnode_map).split.last.strip
|
137
161
|
else
|
138
|
-
solution[n].to_s
|
162
|
+
solution[n].to_s.strip
|
139
163
|
end
|
140
164
|
end
|
141
165
|
end
|
@@ -144,11 +168,9 @@ module SPARQL
|
|
144
168
|
##
|
145
169
|
# Generate Solutions as TSV
|
146
170
|
# @return [String]
|
147
|
-
# @see
|
171
|
+
# @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
|
148
172
|
def to_tsv
|
149
173
|
require 'csv' unless defined?(::CSV)
|
150
|
-
bnode_map = {}
|
151
|
-
bnode_gen = "_:a"
|
152
174
|
results = [
|
153
175
|
variable_names.map {|v| "?#{v}"}.join("\t")
|
154
176
|
] + self.map do |solution|
|
@@ -156,10 +178,15 @@ module SPARQL
|
|
156
178
|
case term = solution[n]
|
157
179
|
when RDF::Literal::Integer, RDF::Literal::Decimal, RDF::Literal::Double
|
158
180
|
term.canonicalize.to_s
|
181
|
+
when RDF::Statement
|
182
|
+
emb_stmt = RDF::Query::Solutions(
|
183
|
+
RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
|
184
|
+
).to_tsv.split("\n").last.strip
|
185
|
+
emb_stmt.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
|
159
186
|
when nil
|
160
187
|
""
|
161
188
|
else
|
162
|
-
RDF::NTriples.serialize(term)
|
189
|
+
RDF::NTriples.serialize(term).strip.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
|
163
190
|
end
|
164
191
|
end.join("\t")
|
165
192
|
end
|
@@ -185,7 +212,7 @@ module SPARQL
|
|
185
212
|
# @return [String]
|
186
213
|
# String with serialized results and `#content_type`
|
187
214
|
# @raise [RDF::WriterError] when inappropriate formatting options are used
|
188
|
-
def serialize_results(solutions, options
|
215
|
+
def serialize_results(solutions, **options)
|
189
216
|
format = options[:format].to_sym if options[:format]
|
190
217
|
content_type = options[:content_type].to_s.split(';').first
|
191
218
|
content_types = Array(options[:content_types] || '*/*')
|
@@ -226,7 +253,7 @@ module SPARQL
|
|
226
253
|
when RDF::Queryable
|
227
254
|
begin
|
228
255
|
require 'linkeddata'
|
229
|
-
rescue LoadError
|
256
|
+
rescue LoadError
|
230
257
|
require 'rdf/ntriples'
|
231
258
|
end
|
232
259
|
fmt = RDF::Format.for(format ? format.to_sym : {content_type: content_type})
|
@@ -236,7 +263,7 @@ module SPARQL
|
|
236
263
|
end
|
237
264
|
format ||= fmt.to_sym
|
238
265
|
content_type ||= fmt.content_type.first
|
239
|
-
results = solutions.dump(format, options)
|
266
|
+
results = solutions.dump(format, **options)
|
240
267
|
raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results
|
241
268
|
results
|
242
269
|
when RDF::Query::Solutions
|
@@ -280,7 +307,7 @@ module SPARQL
|
|
280
307
|
# @param [Array<String>] available
|
281
308
|
# @return [String]
|
282
309
|
#
|
283
|
-
# @see
|
310
|
+
# @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
284
311
|
def first_content_type(acceptable, available)
|
285
312
|
return acceptable.first if available.empty?
|
286
313
|
available.flatten!
|
@@ -306,7 +333,7 @@ module SPARQL
|
|
306
333
|
# May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results
|
307
334
|
# @return [String]
|
308
335
|
# String with serialized results and #content_type
|
309
|
-
def serialize_exception(exception, options
|
336
|
+
def serialize_exception(exception, **options)
|
310
337
|
format = options[:format]
|
311
338
|
content_type = options[:content_type]
|
312
339
|
content_type ||= SPARQL::Results::MIME_TYPES[format]
|
data/lib/sparql/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module SPARQL
|
2
2
|
module VERSION
|
3
|
-
VERSION_FILE = File.
|
3
|
+
VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
|
4
4
|
MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
|
5
5
|
|
6
6
|
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|