diff --git a/lib/sparql/algebra/operator/group_concat.rb b/lib/sparql/algebra/operator/group_concat.rb index e55df69..b0cfeea 100644 --- a/lib/sparql/algebra/operator/group_concat.rb +++ b/lib/sparql/algebra/operator/group_concat.rb @@ -5,6 +5,8 @@ class Operator # # GroupConcat is a set function which performs a string concatenation across the values of an expression with a group. The order of the strings is not specified. The separator character used in the concatenation may be given with the scalar argument SEPARATOR. # + # If all operands are language-tagged strings with the same language (and direction), the result shares the language (and direction). + # # [127] Aggregate::= ... | 'GROUP_CONCAT' '(' 'DISTINCT'? Expression ( ';' 'SEPARATOR' '=' String )? ')' # # @example SPARQL Grammar @@ -72,7 +74,9 @@ def aggregate(solutions = [], **options) # @return [RDF::Term] An arbitrary term # @raise [TypeError] If enum is empty def apply(enum, separator, **options) - RDF::Literal(enum.flatten.map(&:to_s).join(separator.to_s)) + op1_lang = enum.first.language + lang = op1_lang if op1_lang && enum.all? {|v| v.language == op1_lang} + RDF::Literal(enum.flatten.map(&:to_s).join(separator.to_s), language: lang) end ## diff --git a/script/tc b/script/tc index 034fa46..cf54a46 100755 --- a/script/tc +++ b/script/tc @@ -80,7 +80,9 @@ def run_tc(tc, **options) tc.expected.dump(:trig, standard_prefixes: true) : (tc.solutions.is_a?(RDF::Enumerable) ? tc.solutions.dump(:trig, standard_prefixes: true) : - (tc.solutions ? "Vars: #{tc.solutions.variable_names}\n" + tc.solutions.to_sse : ''))) + (tc.solutions.respond_to?(:variable_names) ? + ("Vars: #{tc.solutions.variable_names}\n" + tc.solutions.to_sse) : + (tc.solutions ? tc.solutions.to_sse : '')))) end case tc.name @@ -131,7 +133,9 @@ def run_tc(tc, **options) STDERR.puts "\nActual:\n" + ( actual.is_a?(RDF::Enumerable) ? actual.dump(:trig, standard_prefixes: true) : - "Vars: #{actual.variable_names}\n" + actual.to_sse) + (actual.respond_to?(:variable_names) ? + ("Vars: #{actual.variable_names}\n" + actual.to_sse) : + (actual ? actual.to_sse : ''))) end case tc.form @@ -368,12 +372,12 @@ opts.each do |opt, arg| when '--optimize' then options[:optimize] = true when '--output' then options[:output] = File.open(arg, "w") when '--quiet' - options[:quiet] = true - logger.level = Logger::FATAL + options[:quiet] = true + logger.level = Logger::FATAL when '--sparql10' then options[:sparql10] = true when '--sparql11' then options[:sparql11] = true when '--sparql12' then options[:sparql12] = true - when '--sparqldev' then options[:sparqldev] = true + when '--sparqldev' then options[:sparqldev] = true when '--use11' then options[:use11] = true when '--validate' then options[:validate] = true when '--verbose' then options[:verbose] = true diff --git a/spec/grammar/misc_spec.rb b/spec/grammar/misc_spec.rb index 09b5f18..2d9ca4f 100644 --- a/spec/grammar/misc_spec.rb +++ b/spec/grammar/misc_spec.rb @@ -140,31 +140,31 @@ (triple ?ev ?b))))) } }, - "dawg-optional-filter-005-not-simplified" => { - query: %( - # Double curly braces do NOT get simplified to single curly braces early on, before filters are scoped - PREFIX dc: - PREFIX x: - SELECT ?title ?price - WHERE - { ?book dc:title ?title . - OPTIONAL - { - { - ?book x:price ?price . - FILTER (?title = "TITLE 2") . - } - } . - } - ), - sse: %{(prefix ((dc: ) (x: )) - (project (?title ?price) - (leftjoin - (bgp (triple ?book dc:title ?title)) - (filter (= ?title "TITLE 2") - (bgp (triple ?book x:price ?price)))))) - } - } + #"dawg-optional-filter-005-not-simplified" => { + # query: %( + # # Double curly braces do NOT get simplified to single curly braces early on, before filters are scoped + # PREFIX dc: + # PREFIX x: + # SELECT ?title ?price + # WHERE + # { ?book dc:title ?title . + # OPTIONAL + # { + # { + # ?book x:price ?price . + # FILTER (?title = "TITLE 2") . + # } + # } . + # } + # ), + # sse: %{(prefix ((dc: ) (x: )) + # (project (?title ?price) + # (leftjoin + # (bgp (triple ?book dc:title ?title)) + # (filter (= ?title "TITLE 2") + # (bgp (triple ?book x:price ?price)))))) + # } + #}, }.each do |test, options| it "parses #{test}" do expect(options[:query]).to generate(options[:sse], logger: logger)