activerdf_net7 1.7.1 → 1.7.2
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.
- 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.
|