activerdf_net7 1.7.1 → 1.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/activerdf-sesame/lib/activerdf_sesame/sesame.rb +3 -4
- data/lib/active_rdf/federation/federation_manager.rb +49 -49
- data/lib/active_rdf/objectmanager/reslike +28 -0
- data/lib/active_rdf/query/query.rb.orig +317 -0
- data/lib/active_rdf/queryengine/query.rb +41 -40
- data/lib/active_rdf/storage/federated_store.rb.orig +116 -0
- data/lib/active_rdf_log.rb +3 -2
- metadata +31 -13
@@ -155,8 +155,7 @@ module ActiveRDF
|
|
155
155
|
check_input = [s,p,o]
|
156
156
|
raise ActiveRdfError, "cannot add triple with nil or blank node subject, predicate, or object" if check_input.any? {|r| r.nil? || r.is_a?(Symbol) }
|
157
157
|
|
158
|
-
|
159
|
-
@db.add(params[0], params[1], params[2], wrap_contexts(c))
|
158
|
+
@db.add(*activerdf_to_sesame(s, p, o, c))
|
160
159
|
true
|
161
160
|
rescue Exception => e
|
162
161
|
raise ActiveRdfError, "Sesame add triple failed: #{e.message}"
|
@@ -370,7 +369,7 @@ module ActiveRDF
|
|
370
369
|
}
|
371
370
|
|
372
371
|
# wrap Context
|
373
|
-
params << wrap_contexts(c)
|
372
|
+
params << wrap_contexts(c)
|
374
373
|
|
375
374
|
params
|
376
375
|
end
|
@@ -381,7 +380,7 @@ module ActiveRDF
|
|
381
380
|
def wrap(item, use_nil = false)
|
382
381
|
result =
|
383
382
|
if(item.respond_to?(:uri))
|
384
|
-
if (item.uri.to_s[0..4].match(/http:/).nil?)
|
383
|
+
if (item.uri.to_s[0..4].match(/http:/i).nil?)
|
385
384
|
@valueFactory.createLiteral(item.uri.to_s)
|
386
385
|
else
|
387
386
|
@valueFactory.createURI(item.uri.to_s)
|
@@ -7,7 +7,7 @@ include ActiveRdfBenchmark
|
|
7
7
|
|
8
8
|
module ActiveRDF
|
9
9
|
class FederationManager
|
10
|
-
|
10
|
+
def FederationManager.contexts
|
11
11
|
ConnectionPool.adapters.collect{|adapter| adapter.contexts if adapter.respond_to?(:contexts)}.flatten.compact
|
12
12
|
end
|
13
13
|
|
@@ -15,21 +15,21 @@ module ActiveRDF
|
|
15
15
|
def FederationManager.add(s,p,o,c=nil)
|
16
16
|
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
17
17
|
bench_message << "ADD #{s} - #{p} - #{o} : #{c}" if(bench_message)
|
18
|
-
|
19
|
-
|
18
|
+
# TODO: allow addition of full graphs
|
19
|
+
raise ActiveRdfError, "cannot write without a write-adapter" unless ConnectionPool.write_adapter
|
20
20
|
ConnectionPool.write_adapter.add(s,p,o,c)
|
21
|
-
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
# delete triple s,p,o (context is optional) to the currently selected write-adapter
|
25
25
|
def FederationManager.delete(s,p=nil,o=nil,c=nil)
|
26
26
|
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
27
27
|
bench_message << "DELETE #{s} - #{p} - #{o} : #{c}" if(bench_message)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
raise ActiveRdfError, "cannot write without a write-adapter" unless ConnectionPool.write_adapter
|
29
|
+
# transform wildcard symbols to nil (for the adaptors)
|
30
|
+
s = nil if s.is_a? Symbol
|
31
|
+
p = nil if p.is_a? Symbol
|
32
|
+
o = nil if o.is_a? Symbol
|
33
33
|
ConnectionPool.write_adapter.delete(s,p,o,c)
|
34
34
|
end
|
35
35
|
end
|
@@ -57,56 +57,56 @@ module ActiveRDF
|
|
57
57
|
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
58
58
|
# Only build the benchmark message if we need it
|
59
59
|
bench_message << ((q.class == String) ? q : q.to_sp) if(bench_message)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
# ask each adapter for query results
|
61
|
+
# and yield them consequtively
|
62
|
+
if block_given?
|
63
|
+
ConnectionPool.read_adapters.each do |source|
|
64
|
+
source.execute(q) do |*clauses|
|
65
|
+
yield(*clauses)
|
66
|
+
end
|
66
67
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
68
|
+
else
|
69
|
+
# build Array of results from all sources
|
70
|
+
# TODO: write test for sebastian's select problem
|
71
|
+
# (without distinct, should get duplicates, they
|
72
|
+
# were filtered out when doing results.union)
|
73
|
+
results = []
|
74
|
+
ConnectionPool.read_adapters.each do |source|
|
75
|
+
source_results = source.execute(q)
|
76
|
+
source_results.each do |clauses|
|
77
|
+
results << clauses
|
78
|
+
end
|
78
79
|
end
|
79
|
-
end
|
80
80
|
|
81
|
-
|
82
|
-
|
81
|
+
# count
|
82
|
+
return results.flatten.inject{|mem,c| mem + c} if q.count?
|
83
83
|
|
84
|
-
|
85
|
-
|
84
|
+
# filter the empty results
|
85
|
+
results.reject {|ary| ary.empty? }
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
# remove duplicate results from multiple
|
88
|
+
# adapters if asked for distinct query
|
89
|
+
# (adapters return only distinct results,
|
90
|
+
# but they cannot check duplicates against each other)
|
91
|
+
results.uniq! if q.distinct?
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
# flatten results array if only one select clause
|
94
|
+
# to prevent unnecessarily nested array [[eyal],[renaud],...]
|
95
|
+
results.flatten! if q.select_clauses.size == 1 or q.ask?
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
97
|
+
# remove array (return single value or nil) if asked to
|
98
|
+
if options[:flatten]
|
99
|
+
case results.size
|
100
|
+
when 0
|
101
|
+
results = nil
|
102
|
+
when 1
|
103
|
+
results = results.first
|
104
|
+
end
|
104
105
|
end
|
105
106
|
end
|
106
|
-
end
|
107
107
|
|
108
|
-
|
108
|
+
results
|
109
109
|
end # End benchmark
|
110
110
|
end # End query
|
111
|
-
end
|
112
111
|
end
|
112
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ActiveRDF
|
2
|
+
|
3
|
+
# Helper Module that contains same additional methods that
|
4
|
+
# are expected from classes that want to behave like
|
5
|
+
# RDFS::Resource.
|
6
|
+
#
|
7
|
+
# The module expects that the including class has an uri
|
8
|
+
# method or property.
|
9
|
+
module ResourceLike
|
10
|
+
|
11
|
+
# returns uri of resource, can be overridden in subclasses
|
12
|
+
def to_s
|
13
|
+
"<#{uri}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
# overriding sort based on uri
|
17
|
+
def <=>(other)
|
18
|
+
uri <=> other.uri
|
19
|
+
end
|
20
|
+
|
21
|
+
# NTriple representation of element
|
22
|
+
def to_literal_s
|
23
|
+
"<#{uri}>"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'active_rdf/federation/federation_manager'
|
2
|
+
|
3
|
+
# Represents a query on a datasource, abstract representation of SPARQL
|
4
|
+
# features. Query is passed to federation manager or adapter for execution on
|
5
|
+
# data source. In all clauses symbols represent variables:
|
6
|
+
# Query.new.select(:s).where(:s,:p,:o).
|
7
|
+
module ActiveRDF
|
8
|
+
class Query
|
9
|
+
attr_reader :select_clauses, :where_clauses, :filter_clauses, :sort_clauses, :limits, :offsets, :keywords
|
10
|
+
|
11
|
+
bool_accessor :distinct, :ask, :select, :count, :keyword, :all_types
|
12
|
+
|
13
|
+
# Creates a new query. You may pass a different class that is used for "resource"
|
14
|
+
# type objects instead of RDFS::Resource
|
15
|
+
def initialize(resource_type = RDFS::Resource)
|
16
|
+
@distinct = false
|
17
|
+
@select_clauses = []
|
18
|
+
@where_clauses = []
|
19
|
+
@filter_clauses = {}
|
20
|
+
@sort_clauses = []
|
21
|
+
@limits = nil
|
22
|
+
@offsets = nil
|
23
|
+
@keywords = {}
|
24
|
+
@reasoning = nil
|
25
|
+
@all_types = false
|
26
|
+
@nil_clause_idx = -1
|
27
|
+
set_resource_class(resource_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
<<<<<<< HEAD:lib/active_rdf/queryengine/query.rb
|
31
|
+
# This returns the class that is be used for resources, by default this
|
32
|
+
# is RDFS::Resource
|
33
|
+
def resource_class
|
34
|
+
@resource_class ||= RDFS::Resource
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets the resource_class. Any class may be used, however it is required
|
38
|
+
# that it can be created using the uri of the resource as it's only
|
39
|
+
# parameter and that it has an 'uri' property
|
40
|
+
def set_resource_class(resource_class)
|
41
|
+
raise(ArgumentError, "resource_class must be a class") unless(resource_class.class == Class)
|
42
|
+
|
43
|
+
test = resource_class.new("http://uri")
|
44
|
+
raise(ArgumentError, "Must have an uri property") unless(test.respond_to?(:uri))
|
45
|
+
@resource_class = resource_class
|
46
|
+
end
|
47
|
+
|
48
|
+
=======
|
49
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/query/query.rb
|
50
|
+
def initialize_copy(orig)
|
51
|
+
# dup the instance variables so we're not messing with the original query's values
|
52
|
+
instance_variables.each do |iv|
|
53
|
+
orig_val = instance_variable_get(iv)
|
54
|
+
case orig_val
|
55
|
+
when Array,Hash
|
56
|
+
instance_variable_set(iv,orig_val.dup)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Clears the select clauses
|
62
|
+
def clear_select
|
63
|
+
<<<<<<< HEAD:lib/active_rdf/queryengine/query.rb
|
64
|
+
ActiveRdfLogger::log_debug "Cleared select clause", self
|
65
|
+
=======
|
66
|
+
ActiveRdfLogger::log_debug(self) { "Cleared select clause" }
|
67
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/query/query.rb
|
68
|
+
@select_clauses = []
|
69
|
+
@distinct = false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adds variables to select clause
|
73
|
+
def select *s
|
74
|
+
raise(ActiveRdfError, "variable must be a Symbol") unless s.all?{|var| var.is_a?(Symbol)}
|
75
|
+
@select = true
|
76
|
+
# removing duplicate select clauses
|
77
|
+
@select_clauses.concat(s).uniq!
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
# Adds variables to ask clause (see SPARQL specification)
|
82
|
+
def ask
|
83
|
+
@ask = true
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Request reasoning be performed on query
|
88
|
+
def reasoning(bool)
|
89
|
+
@reasoning = truefalse(bool)
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
def reasoning=(bool)
|
94
|
+
self.reasoning(bool)
|
95
|
+
end
|
96
|
+
|
97
|
+
def reasoning?
|
98
|
+
@reasoning
|
99
|
+
end
|
100
|
+
|
101
|
+
# Set query to ignore language & datatypes for objects
|
102
|
+
def all_types(enabled = true)
|
103
|
+
@all_types = enabled
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
# Adds variables to select distinct clause
|
108
|
+
def distinct *s
|
109
|
+
@distinct = true
|
110
|
+
select(*s)
|
111
|
+
end
|
112
|
+
alias_method :select_distinct, :distinct
|
113
|
+
|
114
|
+
# Adds variables to count clause
|
115
|
+
def count *s
|
116
|
+
@count = true
|
117
|
+
select(*s)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Adds sort predicates
|
121
|
+
#
|
122
|
+
def sort *s
|
123
|
+
s.each do |var|
|
124
|
+
<<<<<<< HEAD:lib/active_rdf/queryengine/query.rb
|
125
|
+
|
126
|
+
=======
|
127
|
+
raise(ActiveRdfError, "variable must be a Symbol") unless var.is_a? Symbol
|
128
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/query/query.rb
|
129
|
+
@sort_clauses << [var,:asc]
|
130
|
+
end
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
# adds reverse sorting predicates
|
135
|
+
def reverse_sort *s
|
136
|
+
s.each do |var|
|
137
|
+
raise(ActiveRdfError, "variable must be a Symbol") unless var.is_a? Symbol
|
138
|
+
@sort_clauses << [var,:desc]
|
139
|
+
end
|
140
|
+
self
|
141
|
+
end
|
142
|
+
|
143
|
+
# adds operator filter on one variable
|
144
|
+
# variable is a Ruby symbol that appears in select/where clause, operator is a
|
145
|
+
# SPARQL operator (e.g. '>','lang','datatype'), operand is a SPARQL value (e.g. 15)
|
146
|
+
def filter(variable, operator, operand)
|
147
|
+
raise(ActiveRdfError, "variable must be a Symbol") unless variable.is_a? Symbol
|
148
|
+
@filter_clauses[variable] = [operator.to_sym,operand]
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
152
|
+
# adds regular expression filter on one variable
|
153
|
+
# variable is Ruby symbol that appears in select/where clause, regex is Ruby
|
154
|
+
# regular expression
|
155
|
+
def regexp(variable, regexp)
|
156
|
+
raise(ActiveRdfError, "variable must be a symbol") unless variable.is_a? Symbol
|
157
|
+
regexp = regexp.source if(regexp.is_a?(Regexp))
|
158
|
+
<<<<<<< HEAD:lib/active_rdf/queryengine/query.rb
|
159
|
+
|
160
|
+
=======
|
161
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/query/query.rb
|
162
|
+
filter(variable, :regexp, regexp)
|
163
|
+
end
|
164
|
+
alias :regex :regexp
|
165
|
+
|
166
|
+
# filter variable on specified language tag, e.g. lang(:o, 'en', true)
|
167
|
+
# optionally matches exactly on language dialect, otherwise only
|
168
|
+
# language-specifier is considered
|
169
|
+
def lang(variable, tag, exact=true)
|
170
|
+
filter(variable,:lang,[tag.sub(/^@/,''),exact])
|
171
|
+
end
|
172
|
+
|
173
|
+
def datatype(variable, type)
|
174
|
+
filter(variable,:datatype,type)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Adds limit clause (maximum number of results to return)
|
178
|
+
def limit(i)
|
179
|
+
@limits = i.to_i
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
183
|
+
# Add offset clause (ignore first n results)
|
184
|
+
def offset(i)
|
185
|
+
@offsets = i.to_i
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
# Adds where clauses (s,p,o) where each constituent is either variable (:s) or
|
190
|
+
# an RDFS::Resource (or equivalent class). Keyword queries are specified with the special :keyword
|
191
|
+
# symbol: Query.new.select(:s).where(:s, :keyword, 'eyal')
|
192
|
+
def where s,p,o,c=nil
|
193
|
+
case p
|
194
|
+
when :keyword
|
195
|
+
# treat keywords in where-clauses specially
|
196
|
+
keyword_where(s,o)
|
197
|
+
else
|
198
|
+
# give nil clauses a unique variable
|
199
|
+
s,p,o = [s,p,o].collect{|clause| clause.nil? ? "nil#{@nil_clause_idx += 1}".to_sym : clause}
|
200
|
+
|
201
|
+
# remove duplicate variable bindings, e.g.
|
202
|
+
# where(:s,type,:o).where(:s,type,:oo) we should remove the second clause,
|
203
|
+
# since it doesn't add anything to the query and confuses the query
|
204
|
+
# generator.
|
205
|
+
# if you construct this query manually, you shouldn't! if your select
|
206
|
+
# variable happens to be in one of the removed clauses: tough luck.
|
207
|
+
unless (s.respond_to?(:uri) or s.is_a?(Symbol)) and (s.class != RDFS::BNode)
|
208
|
+
raise(ActiveRdfError, "Cannot add a where clause with s #{s}: s must be a resource or a variable, is a #{s.class.name}")
|
209
|
+
end
|
210
|
+
unless (p.respond_to?(:uri) or p.is_a?(Symbol)) and (s.class != RDFS::BNode)
|
211
|
+
raise(ActiveRdfError, "Cannot add a where clause with p #{p}: p must be a resource or a variable, is a #{p.class.name}")
|
212
|
+
end
|
213
|
+
raise(ActiveRdfErrror, "Cannot add a where clause where o is a blank node") if(o.class == RDFS::BNode)
|
214
|
+
|
215
|
+
@where_clauses << [s,p,o,c]
|
216
|
+
end
|
217
|
+
self
|
218
|
+
end
|
219
|
+
|
220
|
+
# Adds keyword constraint to the query. You can use all Ferret query syntax in
|
221
|
+
# the constraint (e.g. keyword_where(:s,'eyal|benjamin')
|
222
|
+
def keyword_where s,o
|
223
|
+
@keyword = true
|
224
|
+
if @keywords.include?(s)
|
225
|
+
@keywords[s] = @keywords[s] + ' ' + o
|
226
|
+
else
|
227
|
+
@keywords[s] = o
|
228
|
+
end
|
229
|
+
self
|
230
|
+
end
|
231
|
+
|
232
|
+
# Executes query on data sources. Either returns result as array
|
233
|
+
# (flattened into single value unless specified otherwise)
|
234
|
+
# or executes a block (number of block variables should be
|
235
|
+
# same as number of select variables)
|
236
|
+
#
|
237
|
+
# usage:: results = query.execute
|
238
|
+
# usage:: query.execute do |s,p,o| ... end
|
239
|
+
def execute(options={:flatten => false}, &block)
|
240
|
+
options = {:flatten => true} if options == :flatten
|
241
|
+
|
242
|
+
prepared_query = prepare_query(options)
|
243
|
+
|
244
|
+
if block_given?
|
245
|
+
for result in FederationManager.execute(prepared_query, options.merge(:flatten => false))
|
246
|
+
yield result
|
247
|
+
end
|
248
|
+
else
|
249
|
+
FederationManager.execute(prepared_query, options)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
# Returns query string depending on adapter (e.g. SPARQL, N3QL, etc.)
|
254
|
+
def to_s
|
255
|
+
if ConnectionPool.read_adapters.empty?
|
256
|
+
inspect
|
257
|
+
else
|
258
|
+
ConnectionPool.read_adapters.first.translate(prepare_query)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Returns SPARQL serialisation of query
|
263
|
+
def to_sp
|
264
|
+
<<<<<<< HEAD:lib/active_rdf/queryengine/query.rb
|
265
|
+
require 'queryengine/query2sparql' unless(defined?(Query2SPARQL))
|
266
|
+
=======
|
267
|
+
require 'active_rdf/queryengine/query2sparql' unless(defined?(Query2SPARQL))
|
268
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/query/query.rb
|
269
|
+
Query2SPARQL.translate(self)
|
270
|
+
end
|
271
|
+
|
272
|
+
private
|
273
|
+
def prepare_query(options = {})
|
274
|
+
# leave the original query intact
|
275
|
+
dup = self.dup
|
276
|
+
dup.expand_obj_values
|
277
|
+
# dup.reasoned_query if dup.reasoning?
|
278
|
+
|
279
|
+
# extract options
|
280
|
+
if options.include?(:order)
|
281
|
+
dup.sort(:sort_value)
|
282
|
+
dup.where(:s, options.delete(:order), :sort_value)
|
283
|
+
end
|
284
|
+
|
285
|
+
if options.include?(:reverse_order)
|
286
|
+
dup.reverse_sort(:sort_value)
|
287
|
+
dup.where(:s, options.delete(:reverse_order), :sort_value)
|
288
|
+
end
|
289
|
+
|
290
|
+
dup.limit(options.delete(:limit)) if options.include?(:limit)
|
291
|
+
dup.offset(options.delete(:offset)) if options.include?(:offset)
|
292
|
+
|
293
|
+
dup
|
294
|
+
end
|
295
|
+
|
296
|
+
protected
|
297
|
+
def expand_obj_values
|
298
|
+
new_where_clauses = []
|
299
|
+
@where_clauses.each do |s,p,o,c|
|
300
|
+
if o.respond_to?(:to_ary)
|
301
|
+
o.to_ary.each{|elem| new_where_clauses << [s,p,elem,c]}
|
302
|
+
else
|
303
|
+
new_where_clauses << [s,p,o,c]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
@where_clauses = new_where_clauses
|
307
|
+
end
|
308
|
+
|
309
|
+
# def reasoned_query
|
310
|
+
# new_where_clauses = []
|
311
|
+
# @where_clauses.each do |s,p,o,c|
|
312
|
+
# # other reasoning should be added here
|
313
|
+
# end
|
314
|
+
# @where_clauses += new_where_clauses
|
315
|
+
# end
|
316
|
+
end
|
317
|
+
end
|
@@ -11,9 +11,9 @@ module ActiveRDF
|
|
11
11
|
|
12
12
|
bool_accessor :distinct, :ask, :select, :count, :keyword, :all_types
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
# Creates a new query. You may pass a different class that is used for "resource"
|
15
|
+
# type objects instead of RDFS::Resource
|
16
|
+
def initialize(resource_type = RDFS::Resource)
|
17
17
|
@distinct = false
|
18
18
|
@select_clauses = []
|
19
19
|
@where_clauses = []
|
@@ -25,41 +25,40 @@ module ActiveRDF
|
|
25
25
|
@reasoning = nil
|
26
26
|
@all_types = false
|
27
27
|
@nil_clause_idx = -1
|
28
|
-
|
28
|
+
set_resource_class(resource_type)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
# This returns the class that is be used for resources, by default this
|
32
|
+
# is RDFS::Resource
|
33
|
+
def resource_class
|
34
|
+
@resource_class ||= RDFS::Resource
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
# Sets the resource_class. Any class may be used, however it is required
|
38
|
+
# that it can be created using the uri of the resource as it's only
|
39
|
+
# parameter and that it has an 'uri' property
|
40
|
+
def set_resource_class(resource_class)
|
41
|
+
raise(ArgumentError, "resource_class must be a class") unless(resource_class.class == Class)
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
test = resource_class.new("http://uri")
|
44
|
+
raise(ArgumentError, "Must have an uri property") unless(test.respond_to?(:uri))
|
45
|
+
@resource_class = resource_class
|
46
|
+
end
|
47
47
|
|
48
48
|
def initialize_copy(orig)
|
49
49
|
# dup the instance variables so we're not messing with the original query's values
|
50
50
|
instance_variables.each do |iv|
|
51
51
|
orig_val = instance_variable_get(iv)
|
52
52
|
case orig_val
|
53
|
-
|
54
|
-
|
53
|
+
when Array,Hash
|
54
|
+
instance_variable_set(iv,orig_val.dup)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
59
|
# Clears the select clauses
|
61
60
|
def clear_select
|
62
|
-
|
61
|
+
ActiveRdfLogger::log_debug "Cleared select clause", self
|
63
62
|
@select_clauses = []
|
64
63
|
@distinct = false
|
65
64
|
end
|
@@ -84,9 +83,11 @@ module ActiveRDF
|
|
84
83
|
@reasoning = truefalse(bool)
|
85
84
|
self
|
86
85
|
end
|
86
|
+
|
87
87
|
def reasoning=(bool)
|
88
88
|
self.reasoning(bool)
|
89
89
|
end
|
90
|
+
|
90
91
|
def reasoning?
|
91
92
|
@reasoning
|
92
93
|
end
|
@@ -114,7 +115,7 @@ module ActiveRDF
|
|
114
115
|
#
|
115
116
|
def sort *s
|
116
117
|
s.each do |var|
|
117
|
-
|
118
|
+
|
118
119
|
@sort_clauses << [var,:asc]
|
119
120
|
end
|
120
121
|
self
|
@@ -142,10 +143,10 @@ module ActiveRDF
|
|
142
143
|
# variable is Ruby symbol that appears in select/where clause, regex is Ruby
|
143
144
|
# regular expression
|
144
145
|
def regexp(variable, regexp)
|
145
|
-
|
146
|
-
|
146
|
+
raise(ActiveRdfError, "variable must be a symbol") unless variable.is_a? Symbol
|
147
|
+
regexp = regexp.source if(regexp.is_a?(Regexp))
|
147
148
|
|
148
|
-
|
149
|
+
filter(variable, :regexp, regexp)
|
149
150
|
end
|
150
151
|
alias :regex :regexp
|
151
152
|
|
@@ -173,7 +174,7 @@ module ActiveRDF
|
|
173
174
|
end
|
174
175
|
|
175
176
|
# Adds where clauses (s,p,o) where each constituent is either variable (:s) or
|
176
|
-
|
177
|
+
# an RDFS::Resource (or equivalent class). Keyword queries are specified with the special :keyword
|
177
178
|
# symbol: Query.new.select(:s).where(:s, :keyword, 'eyal')
|
178
179
|
def where s,p,o,c=nil
|
179
180
|
case p
|
@@ -190,13 +191,13 @@ module ActiveRDF
|
|
190
191
|
# generator.
|
191
192
|
# if you construct this query manually, you shouldn't! if your select
|
192
193
|
# variable happens to be in one of the removed clauses: tough luck.
|
193
|
-
|
194
|
-
|
194
|
+
unless (s.respond_to?(:uri) or s.is_a?(Symbol)) and (s.class != RDFS::BNode)
|
195
|
+
raise(ActiveRdfError, "Cannot add a where clause with s #{s}: s must be a resource or a variable, is a #{s.class.name}")
|
195
196
|
end
|
196
|
-
|
197
|
-
|
197
|
+
unless (p.respond_to?(:uri) or p.is_a?(Symbol)) and (s.class != RDFS::BNode)
|
198
|
+
raise(ActiveRdfError, "Cannot add a where clause with p #{p}: p must be a resource or a variable, is a #{p.class.name}")
|
198
199
|
end
|
199
|
-
|
200
|
+
raise(ActiveRdfErrror, "Cannot add a where clause where o is a blank node") if(o.class == RDFS::BNode)
|
200
201
|
|
201
202
|
@where_clauses << [s,p,o,c]
|
202
203
|
end
|
@@ -247,7 +248,7 @@ module ActiveRDF
|
|
247
248
|
|
248
249
|
# Returns SPARQL serialisation of query
|
249
250
|
def to_sp
|
250
|
-
|
251
|
+
require 'queryengine/query2sparql' unless(defined?(Query2SPARQL))
|
251
252
|
Query2SPARQL.translate(self)
|
252
253
|
end
|
253
254
|
|
@@ -288,12 +289,12 @@ module ActiveRDF
|
|
288
289
|
@where_clauses = new_where_clauses
|
289
290
|
end
|
290
291
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
292
|
+
# def reasoned_query
|
293
|
+
# new_where_clauses = []
|
294
|
+
# @where_clauses.each do |s,p,o,c|
|
295
|
+
# # other reasoning should be added here
|
296
|
+
# end
|
297
|
+
# @where_clauses += new_where_clauses
|
298
|
+
# end
|
298
299
|
end
|
299
300
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'active_rdf/federation/connection_pool'
|
2
|
+
|
3
|
+
include ActiveRdfBenchmark
|
4
|
+
|
5
|
+
# Manages the federation of datasources: distributes queries to right
|
6
|
+
# datasources and merges their results
|
7
|
+
|
8
|
+
module ActiveRDF
|
9
|
+
class FederationManager
|
10
|
+
<<<<<<< HEAD:lib/active_rdf/federation/federation_manager.rb
|
11
|
+
def FederationManager.contexts
|
12
|
+
=======
|
13
|
+
def FederationManager.contexts
|
14
|
+
>>>>>>> 9e1004bb8cd871b9a465a676ffde1a3c16790611:lib/active_rdf/storage/federated_store.rb
|
15
|
+
ConnectionPool.adapters.collect{|adapter| adapter.contexts if adapter.respond_to?(:contexts)}.flatten.compact
|
16
|
+
end
|
17
|
+
|
18
|
+
# add triple s,p,o (context is optional) to the currently selected write-adapter
|
19
|
+
def FederationManager.add(s,p,o,c=nil)
|
20
|
+
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
21
|
+
bench_message << "ADD #{s} - #{p} - #{o} : #{c}" if(bench_message)
|
22
|
+
# TODO: allow addition of full graphs
|
23
|
+
raise ActiveRdfError, "cannot write without a write-adapter" unless ConnectionPool.write_adapter
|
24
|
+
ConnectionPool.write_adapter.add(s,p,o,c)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# delete triple s,p,o (context is optional) to the currently selected write-adapter
|
29
|
+
def FederationManager.delete(s,p=nil,o=nil,c=nil)
|
30
|
+
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
31
|
+
bench_message << "DELETE #{s} - #{p} - #{o} : #{c}" if(bench_message)
|
32
|
+
raise ActiveRdfError, "cannot write without a write-adapter" unless ConnectionPool.write_adapter
|
33
|
+
# transform wildcard symbols to nil (for the adaptors)
|
34
|
+
s = nil if s.is_a? Symbol
|
35
|
+
p = nil if p.is_a? Symbol
|
36
|
+
o = nil if o.is_a? Symbol
|
37
|
+
ConnectionPool.write_adapter.delete(s,p,o,c)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# delete every triples about a specified resource
|
42
|
+
def FederationManager.delete_all(resource)
|
43
|
+
delete(resource, nil, nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Clear the store (or the given context)
|
47
|
+
def FederationManager.clear(context=nil)
|
48
|
+
# FIXME: Make sure that all adapters support clearing
|
49
|
+
raise(RuntimeError, "Adapter #{ConnectionPool.write_adapter.class} doesn't support clear") unless(ConnectionPool.write_adapter.respond_to?(:clear))
|
50
|
+
ConnectionPool.write_adapter.clear(context)
|
51
|
+
end
|
52
|
+
|
53
|
+
# executes read-only queries
|
54
|
+
# by distributing query over complete read-pool
|
55
|
+
# and aggregating the results
|
56
|
+
def FederationManager.execute(q, options={:flatten => false})
|
57
|
+
if ConnectionPool.read_adapters.empty?
|
58
|
+
raise ActiveRdfError, "cannot execute query without data sources"
|
59
|
+
end
|
60
|
+
|
61
|
+
benchmark("SPARQL/RDF", Logger::DEBUG) do |bench_message|
|
62
|
+
# Only build the benchmark message if we need it
|
63
|
+
bench_message << ((q.class == String) ? q : q.to_sp) if(bench_message)
|
64
|
+
# ask each adapter for query results
|
65
|
+
# and yield them consequtively
|
66
|
+
if block_given?
|
67
|
+
ConnectionPool.read_adapters.each do |source|
|
68
|
+
source.execute(q) do |*clauses|
|
69
|
+
yield(*clauses)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
# build Array of results from all sources
|
74
|
+
# TODO: write test for sebastian's select problem
|
75
|
+
# (without distinct, should get duplicates, they
|
76
|
+
# were filtered out when doing results.union)
|
77
|
+
results = []
|
78
|
+
ConnectionPool.read_adapters.each do |source|
|
79
|
+
source_results = source.execute(q)
|
80
|
+
source_results.each do |clauses|
|
81
|
+
results << clauses
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# count
|
86
|
+
return results.flatten.inject{|mem,c| mem + c} if q.count?
|
87
|
+
|
88
|
+
# filter the empty results
|
89
|
+
results.reject {|ary| ary.empty? }
|
90
|
+
|
91
|
+
# remove duplicate results from multiple
|
92
|
+
# adapters if asked for distinct query
|
93
|
+
# (adapters return only distinct results,
|
94
|
+
# but they cannot check duplicates against each other)
|
95
|
+
results.uniq! if q.distinct?
|
96
|
+
|
97
|
+
# flatten results array if only one select clause
|
98
|
+
# to prevent unnecessarily nested array [[eyal],[renaud],...]
|
99
|
+
results.flatten! if q.select_clauses.size == 1 or q.ask?
|
100
|
+
|
101
|
+
# remove array (return single value or nil) if asked to
|
102
|
+
if options[:flatten]
|
103
|
+
case results.size
|
104
|
+
when 0
|
105
|
+
results = nil
|
106
|
+
when 1
|
107
|
+
results = results.first
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
results
|
113
|
+
end # End benchmark
|
114
|
+
end # End query
|
115
|
+
end
|
116
|
+
end
|
data/lib/active_rdf_log.rb
CHANGED
@@ -27,6 +27,7 @@ class ActiveRdfLogger
|
|
27
27
|
|
28
28
|
# Assign a new logger
|
29
29
|
def logger=(logger)
|
30
|
+
raise(ArgumentError, "Empty Logger") if(logger == nil)
|
30
31
|
@logger = logger
|
31
32
|
@native_logger = false
|
32
33
|
end
|
@@ -55,8 +56,8 @@ class ActiveRdfLogger
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def get_active_rdf_logger
|
58
|
-
if(defined?(
|
59
|
-
|
59
|
+
if(defined?(Rails) && !Rails.logger.nil?)
|
60
|
+
Rails.logger
|
60
61
|
else
|
61
62
|
@native_logger = true
|
62
63
|
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerdf_net7
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 7
|
8
|
+
- 2
|
9
|
+
version: 1.7.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Eyal Oren
|
@@ -10,29 +15,37 @@ autorequire: active_rdf
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2010-
|
18
|
+
date: 2010-07-19 00:00:00 +02:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
22
|
name: gem_plugin
|
18
|
-
|
19
|
-
|
20
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
25
|
requirements:
|
22
26
|
- - ">="
|
23
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 2
|
31
|
+
- 1
|
24
32
|
version: 0.2.1
|
25
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
26
35
|
- !ruby/object:Gem::Dependency
|
27
36
|
name: grit
|
28
|
-
|
29
|
-
|
30
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
39
|
requirements:
|
32
40
|
- - ">="
|
33
41
|
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 1
|
44
|
+
- 1
|
45
|
+
- 1
|
34
46
|
version: 1.1.1
|
35
|
-
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
36
49
|
description: Offers object-oriented access to RDF (with adapters to several datastores). Version of the Talia project. THIS IS NOT THE OFFICIAL VERSION.
|
37
50
|
email: hahn@netseven.it
|
38
51
|
executables: []
|
@@ -201,13 +214,16 @@ files:
|
|
201
214
|
- lib/active_rdf/objectmanager/property.rb
|
202
215
|
- lib/active_rdf/objectmanager/property_list.rb
|
203
216
|
- lib/active_rdf/objectmanager/property_lookup.rb
|
217
|
+
- lib/active_rdf/objectmanager/reslike
|
204
218
|
- lib/active_rdf/objectmanager/resource.rb
|
205
219
|
- lib/active_rdf/objectmanager/resource_like.rb
|
206
220
|
- lib/active_rdf/objectmanager/resource_query.rb
|
221
|
+
- lib/active_rdf/query/query.rb.orig
|
207
222
|
- lib/active_rdf/queryengine/ntriples_parser.rb
|
208
223
|
- lib/active_rdf/queryengine/query.rb
|
209
224
|
- lib/active_rdf/queryengine/query2jars2.rb
|
210
225
|
- lib/active_rdf/queryengine/query2sparql.rb
|
226
|
+
- lib/active_rdf/storage/federated_store.rb.orig
|
211
227
|
- lib/active_rdf_helpers.rb
|
212
228
|
- lib/active_rdf_log.rb
|
213
229
|
- CHANGELOG
|
@@ -226,18 +242,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
226
242
|
requirements:
|
227
243
|
- - ">="
|
228
244
|
- !ruby/object:Gem::Version
|
245
|
+
segments:
|
246
|
+
- 0
|
229
247
|
version: "0"
|
230
|
-
version:
|
231
248
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
249
|
requirements:
|
233
250
|
- - ">="
|
234
251
|
- !ruby/object:Gem::Version
|
252
|
+
segments:
|
253
|
+
- 0
|
235
254
|
version: "0"
|
236
|
-
version:
|
237
255
|
requirements: []
|
238
256
|
|
239
257
|
rubyforge_project:
|
240
|
-
rubygems_version: 1.3.
|
258
|
+
rubygems_version: 1.3.6
|
241
259
|
signing_key:
|
242
260
|
specification_version: 3
|
243
261
|
summary: Offers object-oriented access to RDF (with adapters to several datastores). Version of the Talia project.
|