sparql 3.0.1 → 3.1.4
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 +188 -73
- 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 +63 -40
- data/lib/sparql/algebra/extensions.rb +180 -33
- data/lib/sparql/algebra/operator.rb +37 -16
- 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 +6 -4
- data/lib/sparql/algebra/operator/base.rb +10 -10
- data/lib/sparql/algebra/operator/bgp.rb +1 -1
- 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 +15 -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 +6 -4
- data/lib/sparql/algebra/operator/md5.rb +1 -1
- data/lib/sparql/algebra/operator/min.rb +6 -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 +3 -3
- 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 +5 -5
- data/lib/sparql/grammar.rb +111 -11
- data/lib/sparql/grammar/meta.rb +2340 -907
- data/lib/sparql/grammar/parser11.rb +69 -69
- data/lib/sparql/grammar/terminals11.rb +2 -0
- data/lib/sparql/results.rb +73 -46
- data/lib/sparql/version.rb +1 -1
- metadata +38 -65
@@ -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
|
@@ -216,7 +216,7 @@ module SPARQL::Grammar
|
|
216
216
|
unless resolve_iris?
|
217
217
|
# Only output if we're not resolving URIs internally
|
218
218
|
add_prod_datum(:BaseDecl, data[:BaseDecl])
|
219
|
-
add_prod_datum(:PrefixDecl, data[:PrefixDecl])
|
219
|
+
add_prod_datum(:PrefixDecl, data[:PrefixDecl])
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
@@ -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
|
@@ -624,11 +624,14 @@ module SPARQL::Grammar
|
|
624
624
|
if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
|
625
625
|
query = SPARQL::Algebra::Operator::Join.new(lhs, query)
|
626
626
|
end
|
627
|
+
if data[:path]
|
628
|
+
query = SPARQL::Algebra::Operator::Join.new(query, Array(data[:path]).first)
|
629
|
+
end
|
627
630
|
add_prod_datum(:query, query)
|
628
631
|
elsif !Array(data[:query]).empty?
|
629
632
|
# Join query and path
|
630
633
|
add_prod_datum(:query, SPARQL::Algebra::Operator::Join.new(data[:path].first, data[:query].first))
|
631
|
-
|
634
|
+
elsif data[:path]
|
632
635
|
add_prod_datum(:query, data[:path])
|
633
636
|
end
|
634
637
|
end
|
@@ -698,9 +701,9 @@ module SPARQL::Grammar
|
|
698
701
|
end
|
699
702
|
end
|
700
703
|
|
701
|
-
# [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
|
704
|
+
# [60] Bind ::= 'BIND' '(' (Expression || EmbTP) 'AS' Var ')'
|
702
705
|
production(:Bind) do |input, data, callback|
|
703
|
-
add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
|
706
|
+
add_prod_datum :extend, [(data[:Expression] || data[:pattern]).unshift(data[:Var].first)]
|
704
707
|
end
|
705
708
|
|
706
709
|
# [61] InlineData ::= 'VALUES' DataBlock
|
@@ -856,25 +859,30 @@ module SPARQL::Grammar
|
|
856
859
|
data[:Subject] = prod_data[:Subject]
|
857
860
|
error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
|
858
861
|
error(nil, "Expected Verb", production: :ObjectList) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
|
859
|
-
if prod_data[:Verb]
|
860
|
-
|
861
|
-
else
|
862
|
-
data[:VerbPath] = prod_data[:VerbPath]
|
863
|
-
end
|
862
|
+
data[:Verb] = prod_data[:Verb] if prod_data[:Verb]
|
863
|
+
data[:VerbPath] = prod_data[:VerbPath] if prod_data[:VerbPath]
|
864
864
|
end
|
865
865
|
production(:ObjectList) do |input, data, callback|
|
866
866
|
add_prod_datum(:pattern, data[:pattern])
|
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]
|
873
881
|
if object
|
874
882
|
if prod_data[:Verb]
|
875
883
|
add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
|
876
884
|
add_prod_datum(:pattern, data[:pattern])
|
877
|
-
|
885
|
+
elsif prod_data[:VerbPath]
|
878
886
|
add_prod_datum(:path,
|
879
887
|
SPARQL::Algebra::Expression(:path,
|
880
888
|
prod_data[:Subject].first,
|
@@ -886,11 +894,8 @@ module SPARQL::Grammar
|
|
886
894
|
|
887
895
|
# [81] TriplesSameSubjectPath ::= VarOrTerm PropertyListPathNotEmpty | TriplesNode PropertyListPath
|
888
896
|
production(:TriplesSameSubjectPath) do |input, data, callback|
|
889
|
-
|
890
|
-
|
891
|
-
else
|
892
|
-
add_prod_datum(:path, data[:path])
|
893
|
-
end
|
897
|
+
add_prod_datum(:pattern, data[:pattern])
|
898
|
+
add_prod_datum(:path, data[:path])
|
894
899
|
end
|
895
900
|
|
896
901
|
# [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
|
@@ -900,16 +905,14 @@ module SPARQL::Grammar
|
|
900
905
|
data[:Subject] = subject
|
901
906
|
end
|
902
907
|
production(:PropertyListPathNotEmpty) do |input, data, callback|
|
903
|
-
|
904
|
-
|
905
|
-
else
|
906
|
-
add_prod_datum(:path, data[:path])
|
907
|
-
end
|
908
|
+
add_prod_datum(:pattern, data[:pattern])
|
909
|
+
add_prod_datum(:path, data[:path])
|
908
910
|
end
|
909
911
|
|
910
912
|
# [84] VerbPath ::= Path
|
911
913
|
production(:VerbPath) do |input, data, callback|
|
912
914
|
if data[:Path]
|
915
|
+
input.delete(:Verb)
|
913
916
|
input[:VerbPath] = data[:Path]
|
914
917
|
else
|
915
918
|
input[:Verb] = data[:iri]
|
@@ -1109,6 +1112,11 @@ module SPARQL::Grammar
|
|
1109
1112
|
data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
|
1110
1113
|
end
|
1111
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
|
+
|
1112
1120
|
# [107] VarOrIri ::= Var | iri
|
1113
1121
|
production(:VarOrIri) do |input, data, callback|
|
1114
1122
|
data.values.each {|v| add_prod_datum(:VarOrIri, v)}
|
@@ -1124,6 +1132,22 @@ module SPARQL::Grammar
|
|
1124
1132
|
data[:NIL])
|
1125
1133
|
end
|
1126
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
|
+
|
1127
1151
|
# [110] Expression ::= ConditionalOrExpression
|
1128
1152
|
production(:Expression) do |input, data, callback|
|
1129
1153
|
add_prod_datum(:Expression, data[:Expression])
|
@@ -1420,7 +1444,7 @@ module SPARQL::Grammar
|
|
1420
1444
|
str = lit.delete(:string)
|
1421
1445
|
lit[:datatype] = lit.delete(:iri) if lit[:iri]
|
1422
1446
|
lit[:language] = lit.delete(:language).last.downcase if lit[:language]
|
1423
|
-
input[:literal] = RDF::Literal.new(str, lit) if str
|
1447
|
+
input[:literal] = RDF::Literal.new(str, **lit) if str
|
1424
1448
|
end
|
1425
1449
|
end
|
1426
1450
|
|
@@ -1463,25 +1487,19 @@ module SPARQL::Grammar
|
|
1463
1487
|
# definitions.
|
1464
1488
|
# @option options [Boolean] :validate (false)
|
1465
1489
|
# whether to validate the parsed statements and values
|
1466
|
-
# @option options [
|
1467
|
-
#
|
1468
|
-
# @option options [Boolean] :debug
|
1469
|
-
# Detailed debug output
|
1490
|
+
# @option options [Logger, #write, #<<] :logger
|
1491
|
+
# Record error/info/debug output
|
1470
1492
|
# @yield [parser] `self`
|
1471
1493
|
# @yieldparam [SPARQL::Grammar::Parser] parser
|
1472
1494
|
# @yieldreturn [void] ignored
|
1473
1495
|
# @return [SPARQL::Grammar::Parser]
|
1474
|
-
def initialize(input = nil, options
|
1496
|
+
def initialize(input = nil, **options, &block)
|
1475
1497
|
@input = case input
|
1476
1498
|
when IO, StringIO then input.read
|
1477
1499
|
else input.to_s.dup
|
1478
1500
|
end
|
1479
1501
|
@input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
|
1480
1502
|
@options = {anon_base: "b0", validate: false}.merge(options)
|
1481
|
-
@options[:debug] ||= case
|
1482
|
-
when options[:progress] then 2
|
1483
|
-
when options[:validate] then 1
|
1484
|
-
end
|
1485
1503
|
|
1486
1504
|
debug("base IRI") {base_uri.inspect}
|
1487
1505
|
debug("validate") {validate?.inspect}
|
@@ -1532,30 +1550,17 @@ module SPARQL::Grammar
|
|
1532
1550
|
# @param [Symbol, #to_s] prod The starting production for the parser.
|
1533
1551
|
# It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
|
1534
1552
|
# @return [Array]
|
1535
|
-
# @see
|
1536
|
-
# @see
|
1553
|
+
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
1554
|
+
# @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
|
1537
1555
|
def parse(prod = START)
|
1538
|
-
ll1_parse(@input,
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
message = args.to_sse
|
1547
|
-
d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
|
1548
|
-
str = "[#{lineno}](#{level})#{d_str}#{message}".chop
|
1549
|
-
case @options[:debug]
|
1550
|
-
when Array
|
1551
|
-
@options[:debug] << str unless level > 2
|
1552
|
-
when TrueClass
|
1553
|
-
$stderr.puts str
|
1554
|
-
when Integer
|
1555
|
-
$stderr.puts(str) if level <= @options[:debug]
|
1556
|
-
end
|
1557
|
-
end
|
1558
|
-
end
|
1556
|
+
ll1_parse(@input,
|
1557
|
+
prod.to_sym,
|
1558
|
+
branch: BRANCH,
|
1559
|
+
first: FIRST,
|
1560
|
+
follow: FOLLOW,
|
1561
|
+
whitespace: WS,
|
1562
|
+
**@options
|
1563
|
+
)
|
1559
1564
|
|
1560
1565
|
# The last thing on the @prod_data stack is the result
|
1561
1566
|
@result = case
|
@@ -1723,9 +1728,7 @@ module SPARQL::Grammar
|
|
1723
1728
|
|
1724
1729
|
if id
|
1725
1730
|
@vars[id] ||= begin
|
1726
|
-
|
1727
|
-
v.distinguished = distinguished
|
1728
|
-
v
|
1731
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1729
1732
|
end
|
1730
1733
|
else
|
1731
1734
|
unless distinguished
|
@@ -1733,9 +1736,7 @@ module SPARQL::Grammar
|
|
1733
1736
|
id = @nd_var_gen
|
1734
1737
|
@nd_var_gen = id.succ
|
1735
1738
|
end
|
1736
|
-
|
1737
|
-
v.distinguished = distinguished
|
1738
|
-
v
|
1739
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
1739
1740
|
end
|
1740
1741
|
end
|
1741
1742
|
|
@@ -1763,7 +1764,7 @@ module SPARQL::Grammar
|
|
1763
1764
|
end
|
1764
1765
|
|
1765
1766
|
# Create a literal
|
1766
|
-
def literal(value, options
|
1767
|
+
def literal(value, **options)
|
1767
1768
|
options = options.dup
|
1768
1769
|
# Internal representation is to not use xsd:string, although it could arguably go the other way.
|
1769
1770
|
options.delete(:datatype) if options[:datatype] == RDF::XSD.string
|
@@ -1772,7 +1773,7 @@ module SPARQL::Grammar
|
|
1772
1773
|
"options: #{options.inspect}, " +
|
1773
1774
|
"validate: #{validate?.inspect}, "
|
1774
1775
|
end
|
1775
|
-
RDF::Literal.new(value,
|
1776
|
+
RDF::Literal.new(value, validate: validate?, **options)
|
1776
1777
|
end
|
1777
1778
|
|
1778
1779
|
# Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
|
@@ -1803,7 +1804,7 @@ module SPARQL::Grammar
|
|
1803
1804
|
#
|
1804
1805
|
# @param [String] production Production generating pattern
|
1805
1806
|
# @param [Hash{Symbol => Object}] options
|
1806
|
-
def add_pattern(production, options)
|
1807
|
+
def add_pattern(production, **options)
|
1807
1808
|
progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
|
1808
1809
|
triple = {}
|
1809
1810
|
options.each_pair do |r, v|
|
@@ -1885,8 +1886,7 @@ module SPARQL::Grammar
|
|
1885
1886
|
avf.first
|
1886
1887
|
else
|
1887
1888
|
# Allocate a temporary variable for this function, and retain the mapping for outside the group
|
1888
|
-
av = RDF::Query::Variable.new(".#{agg}")
|
1889
|
-
av.distinguished = false
|
1889
|
+
av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
|
1890
1890
|
agg += 1
|
1891
1891
|
aggregates << [av, function]
|
1892
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]
|