pacer 0.9.1.1-java → 1.0.0-java
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/.autotest +4 -1
- data/.gitignore +4 -0
- data/.rspec +1 -1
- data/Gemfile-dev +33 -0
- data/Gemfile-release +4 -0
- data/README.md +27 -9
- data/Rakefile +26 -8
- data/bin/autotest +1 -1
- data/lib/pacer/blueprints/multi_graph.rb +7 -19
- data/lib/pacer/blueprints/ruby_graph.rb +77 -52
- data/lib/pacer/blueprints/tg.rb +6 -93
- data/lib/pacer/blueprints.rb +0 -1
- data/lib/pacer/core/graph/edges_route.rb +10 -12
- data/lib/pacer/core/graph/element_route.rb +14 -21
- data/lib/pacer/core/graph/graph_index_route.rb +12 -8
- data/lib/pacer/core/graph/graph_route.rb +2 -5
- data/lib/pacer/core/graph/mixed_route.rb +3 -5
- data/lib/pacer/core/graph/vertices_route.rb +26 -27
- data/lib/pacer/core/route.rb +35 -66
- data/lib/pacer/exceptions.rb +13 -6
- data/lib/pacer/extensions/block_filter_element.rb +0 -5
- data/lib/pacer/filter/collection_filter.rb +9 -2
- data/lib/pacer/filter/empty_filter.rb +12 -3
- data/lib/pacer/filter/future_filter.rb +5 -5
- data/lib/pacer/filter/loop_filter.rb +7 -13
- data/lib/pacer/filter/object_filter.rb +10 -16
- data/lib/pacer/filter/property_filter/filters.rb +134 -93
- data/lib/pacer/filter/property_filter.rb +22 -19
- data/lib/pacer/filter/where_filter/node_visitor.rb +47 -26
- data/lib/pacer/filter/where_filter.rb +24 -3
- data/lib/pacer/function_resolver.rb +7 -2
- data/lib/pacer/graph/graph_ml.rb +39 -0
- data/lib/pacer/graph/graph_transactions_mixin.rb +107 -175
- data/lib/pacer/graph/pacer_graph.rb +438 -0
- data/lib/pacer/graph/simple_encoder.rb +20 -0
- data/lib/pacer/graph/yaml_encoder.rb +81 -0
- data/lib/pacer/graph.rb +8 -10
- data/lib/pacer/pipe/blackbox_pipeline.rb +11 -4
- data/lib/pacer/pipe/block_filter_pipe.rb +5 -22
- data/lib/pacer/pipe/cross_product_transform_pipe.rb +5 -7
- data/lib/pacer/pipe/edges_pipe.rb +22 -0
- data/lib/pacer/pipe/enumerable_pipe.rb +3 -9
- data/lib/pacer/pipe/expandable_pipe.rb +2 -14
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +2 -8
- data/lib/pacer/pipe/is_empty_pipe.rb +5 -12
- data/lib/pacer/pipe/is_unique_pipe.rb +3 -13
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +1 -7
- data/lib/pacer/pipe/label_prefix_pipe.rb +0 -6
- data/lib/pacer/pipe/loop_pipe.rb +27 -25
- data/lib/pacer/pipe/never_pipe.rb +1 -1
- data/lib/pacer/pipe/path_wrapping_pipe.rb +40 -0
- data/lib/pacer/pipe/process_pipe.rb +2 -20
- data/lib/pacer/pipe/property_comparison_pipe.rb +0 -6
- data/lib/pacer/pipe/ruby_pipe.rb +10 -3
- data/lib/pacer/pipe/simple_visitor_pipe.rb +12 -11
- data/lib/pacer/pipe/stream_sort_pipe.rb +1 -7
- data/lib/pacer/pipe/stream_uniq_pipe.rb +0 -6
- data/lib/pacer/pipe/type_filter_pipe.rb +1 -7
- data/lib/pacer/pipe/unary_transform_pipe.rb +6 -8
- data/lib/pacer/pipe/unwrapping_pipe.rb +13 -0
- data/lib/pacer/pipe/vertices_pipe.rb +22 -0
- data/lib/pacer/pipe/visitor_pipe.rb +3 -7
- data/lib/pacer/pipe/wrapping_pipe.rb +37 -0
- data/lib/pacer/pipes.rb +17 -12
- data/lib/pacer/route/mixin/bulk_operations.rb +8 -9
- data/lib/pacer/route/mixin/route_operations.rb +17 -11
- data/lib/pacer/route/mixins.rb +0 -1
- data/lib/pacer/route.rb +198 -121
- data/lib/pacer/side_effect/aggregate.rb +22 -2
- data/lib/pacer/side_effect/as.rb +73 -0
- data/lib/pacer/side_effect/group_count.rb +0 -3
- data/lib/pacer/side_effect/is_unique.rb +7 -6
- data/lib/pacer/side_effect.rb +1 -1
- data/lib/pacer/support/enumerable.rb +14 -12
- data/lib/pacer/support/nil_class.rb +5 -0
- data/lib/pacer/support/proc.rb +2 -2
- data/lib/pacer/support.rb +1 -1
- data/lib/pacer/transform/cap.rb +1 -1
- data/lib/pacer/transform/has_count_cap.rb +1 -1
- data/lib/pacer/transform/join.rb +20 -16
- data/lib/pacer/transform/map.rb +6 -2
- data/lib/pacer/transform/path.rb +44 -20
- data/lib/pacer/transform/sort_section.rb +58 -51
- data/lib/pacer/utils/tsort.rb +7 -2
- data/lib/pacer/utils.rb +0 -1
- data/lib/pacer/version.rb +4 -3
- data/lib/pacer/visitors/section.rb +42 -0
- data/lib/pacer/visitors/visits_section.rb +32 -0
- data/lib/pacer/visitors.rb +7 -0
- data/lib/pacer/wrappers/edge_wrapper.rb +164 -11
- data/lib/pacer/wrappers/element_wrapper.rb +133 -8
- data/lib/pacer/wrappers/index_wrapper.rb +47 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +175 -12
- data/lib/pacer/wrappers/wrapper_selector.rb +40 -0
- data/lib/pacer/wrappers/wrapping_pipe_function.rb +90 -0
- data/lib/pacer/wrappers.rb +3 -1
- data/lib/pacer-1.0.0-standalone.jar +0 -0
- data/lib/pacer.rb +13 -47
- data/pacer.gemspec +0 -8
- data/pom.xml +10 -3
- data/spec/pacer/blueprints/dex_spec.rb +12 -26
- data/spec/pacer/blueprints/neo4j_spec.rb +14 -28
- data/spec/pacer/blueprints/tg_spec.rb +6 -54
- data/spec/pacer/core/graph/edges_route_spec.rb +1 -1
- data/spec/pacer/core/graph/element_route_spec.rb +2 -2
- data/spec/pacer/core/graph/graph_route_spec.rb +2 -2
- data/spec/pacer/core/graph/vertices_route_spec.rb +10 -3
- data/spec/pacer/core/route_spec.rb +35 -58
- data/spec/pacer/filter/empty_filter_spec.rb +5 -6
- data/spec/pacer/filter/future_filter_spec.rb +8 -8
- data/spec/pacer/filter/loop_filter_spec.rb +120 -6
- data/spec/pacer/filter/object_filter_spec.rb +15 -0
- data/spec/pacer/filter/property_filter/filters_spec.rb +169 -0
- data/spec/pacer/filter/property_filter_spec.rb +15 -12
- data/spec/pacer/filter/uniq_filter_spec.rb +1 -1
- data/spec/pacer/filter/where_filter_spec.rb +55 -7
- data/spec/pacer/graph/{graph_mixin_spec.rb → pacer_graph_spec.rb} +114 -185
- data/spec/pacer/route/mixin/base_spec.rb +36 -35
- data/spec/pacer/route/mixin/route_operations_spec.rb +4 -46
- data/spec/pacer/side_effect/as_spec.rb +34 -0
- data/spec/pacer/support/enumerable_spec.rb +6 -6
- data/spec/pacer/transform/join_spec.rb +7 -5
- data/spec/pacer/transform/map_spec.rb +55 -0
- data/spec/pacer/transform/path_spec.rb +30 -15
- data/spec/pacer/transform/process_spec.rb +42 -0
- data/spec/pacer/transform/sort_section_spec.rb +82 -0
- data/spec/pacer/wrapper/edge_wrapper_spec.rb +122 -2
- data/spec/pacer/wrapper/element_wrapper_spec.rb +289 -3
- data/spec/pacer/wrapper/vertex_wrapper_spec.rb +289 -2
- data/spec/spec_helper.rb +16 -7
- data/spec/support/graph_runner.rb +80 -29
- data/tags +1165 -0
- metadata +46 -107
- data/.rvmrc +0 -0
- data/lib/pacer/blueprints/extensions.rb +0 -77
- data/lib/pacer/graph/edge_mixin.rb +0 -127
- data/lib/pacer/graph/element_mixin.rb +0 -202
- data/lib/pacer/graph/graph_indices_mixin.rb +0 -93
- data/lib/pacer/graph/graph_mixin.rb +0 -361
- data/lib/pacer/graph/index_mixin.rb +0 -30
- data/lib/pacer/graph/vertex_mixin.rb +0 -119
- data/lib/pacer/pipe/map_pipe.rb +0 -36
- data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +0 -26
- data/lib/pacer/route/mixin/variable_route_module.rb +0 -26
- data/lib/pacer/side_effect/section.rb +0 -25
- data/lib/pacer/support/iterator_mixins.rb +0 -110
- data/lib/pacer/wrappers/new_element.rb +0 -106
- data/lib/pacer-0.9.1.1-standalone.jar +0 -0
- data/spec/pacer/graph/edge_mixin_spec.rb +0 -116
- data/spec/pacer/graph/element_mixin_spec.rb +0 -297
- data/spec/pacer/graph/index_mixin_spec.rb +0 -0
- data/spec/pacer/graph/vertex_mixin_spec.rb +0 -192
@@ -1,6 +1,6 @@
|
|
1
1
|
module Pacer
|
2
|
-
module
|
3
|
-
module
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
4
|
def loop(&block)
|
5
5
|
chain_route :filter => :loop, :looping_route => block
|
6
6
|
end
|
@@ -16,7 +16,7 @@ module Pacer
|
|
16
16
|
arg.to_enum(:times).inject(self) do |route_end, count|
|
17
17
|
yield route_end
|
18
18
|
end
|
19
|
-
when Range
|
19
|
+
when Range
|
20
20
|
if arg.exclude_end?
|
21
21
|
range = arg.begin..(arg.end - 1)
|
22
22
|
else
|
@@ -36,18 +36,12 @@ module Pacer
|
|
36
36
|
r.while_description = "repeat #{ arg.inspect }"
|
37
37
|
r
|
38
38
|
else
|
39
|
-
|
39
|
+
fail ArgumentError, "Invalid repeat range"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
module ElementMixin
|
46
|
-
def loop(&block)
|
47
|
-
chain_route :filter => :loop, :looping_route => block
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
45
|
module Filter
|
52
46
|
module LoopFilter
|
53
47
|
attr_reader :looping_route
|
@@ -61,8 +55,7 @@ module Pacer
|
|
61
55
|
end
|
62
56
|
end
|
63
57
|
|
64
|
-
def while(
|
65
|
-
@yield_paths = yield_paths
|
58
|
+
def while(&block)
|
66
59
|
@control_block = block
|
67
60
|
self
|
68
61
|
end
|
@@ -71,8 +64,9 @@ module Pacer
|
|
71
64
|
|
72
65
|
def attach_pipe(end_pipe)
|
73
66
|
unless @control_block
|
74
|
-
|
67
|
+
fail ClientError, 'No loop control block specified. Use either #while or #until after #loop.'
|
75
68
|
end
|
69
|
+
|
76
70
|
pipe = Pacer::Pipes::LoopPipe.new(graph, looping_pipe, @control_block)
|
77
71
|
pipe.setStarts(end_pipe) if end_pipe
|
78
72
|
pipe
|
@@ -2,30 +2,24 @@ module Pacer
|
|
2
2
|
module Routes
|
3
3
|
module RouteOperations
|
4
4
|
def is(value)
|
5
|
-
if value.
|
6
|
-
|
7
|
-
only(value)
|
5
|
+
if value.is_a? Symbol
|
6
|
+
chain_route :filter => :property, :block => proc { |v| v.vars[value] == v }
|
8
7
|
else
|
9
|
-
|
10
|
-
chain_route :filter => :property, :block => proc { |v| v.vars[value] == v }
|
11
|
-
else
|
12
|
-
chain_route({ :filter => :object, :value => value })
|
13
|
-
end
|
8
|
+
chain_route({ :filter => :object, :value => value })
|
14
9
|
end
|
15
10
|
end
|
16
11
|
|
17
12
|
def is_not(value)
|
18
|
-
if value.
|
19
|
-
|
20
|
-
except(value)
|
13
|
+
if value.is_a? Symbol
|
14
|
+
chain_route :filter => :property, :block => proc { |v| v.vars[value] != v }
|
21
15
|
else
|
22
|
-
|
23
|
-
chain_route :filter => :property, :block => proc { |v| v.vars[value] != v }
|
24
|
-
else
|
25
|
-
chain_route({ :filter => :object, :value => value, :negate => true })
|
26
|
-
end
|
16
|
+
chain_route({ :filter => :object, :value => value, :negate => true })
|
27
17
|
end
|
28
18
|
end
|
19
|
+
|
20
|
+
def compact
|
21
|
+
is_not nil
|
22
|
+
end
|
29
23
|
end
|
30
24
|
end
|
31
25
|
|
@@ -1,8 +1,40 @@
|
|
1
1
|
module Pacer
|
2
2
|
module Filter
|
3
|
+
class KeyIndex
|
4
|
+
attr_reader :graph, :element_type
|
5
|
+
|
6
|
+
def initialize(graph, element_type)
|
7
|
+
@graph = graph
|
8
|
+
@element_type = element_type
|
9
|
+
end
|
10
|
+
|
11
|
+
# FIXME: there is no count for key indices anymore. I'm counting
|
12
|
+
# up to 10 elements to try to find good indices, otherwise using
|
13
|
+
# anything...
|
14
|
+
def count(key, value)
|
15
|
+
iter = get(key, value).iterator
|
16
|
+
10.times do |n|
|
17
|
+
if iter.hasNext
|
18
|
+
iter.next
|
19
|
+
else
|
20
|
+
return n
|
21
|
+
end
|
22
|
+
end
|
23
|
+
1_000_000 # Random high number.
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(key, value)
|
27
|
+
if element_type == :vertex
|
28
|
+
graph.blueprints_graph.getVertices(key, value)
|
29
|
+
else
|
30
|
+
graph.blueprints_graph.getEdges(key, value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
3
35
|
module PropertyFilter
|
4
36
|
class Filters
|
5
|
-
attr_reader :properties, :extensions, :route_modules
|
37
|
+
attr_reader :properties, :extensions, :route_modules, :best_index_value
|
6
38
|
attr_accessor :wrapper, :blocks
|
7
39
|
|
8
40
|
# Allow Pacer to use index counts to determine which index has
|
@@ -25,11 +57,11 @@ module Pacer
|
|
25
57
|
# @attr [Boolean] search_manual_indices
|
26
58
|
attr_accessor :search_manual_indices
|
27
59
|
|
28
|
-
|
60
|
+
protected
|
29
61
|
|
30
62
|
attr_accessor :non_ext_props
|
31
63
|
|
32
|
-
|
64
|
+
public
|
33
65
|
|
34
66
|
def initialize(filters)
|
35
67
|
@properties = []
|
@@ -47,7 +79,7 @@ module Pacer
|
|
47
79
|
# @note this is not threadsafe if you are reusing predefined
|
48
80
|
# routes on multiple graphs.
|
49
81
|
#
|
50
|
-
# @attr [
|
82
|
+
# @attr [PacerGraph] g a graph
|
51
83
|
attr_reader :graph
|
52
84
|
|
53
85
|
def graph=(g)
|
@@ -70,55 +102,6 @@ module Pacer
|
|
70
102
|
end
|
71
103
|
end
|
72
104
|
|
73
|
-
def add_filter(filter, extension)
|
74
|
-
case filter
|
75
|
-
when Hash
|
76
|
-
reset_properties
|
77
|
-
filter.each do |k, v|
|
78
|
-
self.non_ext_props << [k.to_s, v] unless extension
|
79
|
-
self.properties << [k.to_s, v]
|
80
|
-
end
|
81
|
-
when Module, Class
|
82
|
-
if filter.is_a? Class and filter.ancestors.include? Pacer::Wrappers::ElementWrapper
|
83
|
-
self.wrapper = filter
|
84
|
-
else
|
85
|
-
self.extensions << filter
|
86
|
-
end
|
87
|
-
if filter.respond_to? :route_conditions
|
88
|
-
add_filters filter.route_conditions, filter
|
89
|
-
end
|
90
|
-
if filter.respond_to? :route
|
91
|
-
self.route_modules << filter
|
92
|
-
end
|
93
|
-
when Array
|
94
|
-
add_filters(filter, extension)
|
95
|
-
when nil
|
96
|
-
else
|
97
|
-
raise "Unknown filter: #{ filter.class }: #{ filter.inspect }"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def add_filters(filters, extension)
|
102
|
-
if filters.is_a? Array
|
103
|
-
filters.each do |filter|
|
104
|
-
add_filter filter, extension
|
105
|
-
end
|
106
|
-
else
|
107
|
-
add_filter filters, extension
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def encode_value(value)
|
112
|
-
value = graph.encode_property(value)
|
113
|
-
if value.respond_to? :to_java
|
114
|
-
jvalue = value.to_java
|
115
|
-
elsif value.respond_to? :to_java_string
|
116
|
-
jvalue = value.to_java_string
|
117
|
-
else
|
118
|
-
jvalue = value
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
105
|
def build_pipeline(route, start_pipe, pipe = nil)
|
123
106
|
self.graph = route.graph
|
124
107
|
pipe ||= start_pipe
|
@@ -173,39 +156,77 @@ module Pacer
|
|
173
156
|
result
|
174
157
|
end
|
175
158
|
|
176
|
-
|
159
|
+
protected
|
160
|
+
|
161
|
+
def add_filter(filter, extension)
|
162
|
+
case filter
|
163
|
+
when Hash
|
164
|
+
reset_properties
|
165
|
+
filter.each do |k, v|
|
166
|
+
self.non_ext_props << [k.to_s, v] unless extension
|
167
|
+
self.properties << [k.to_s, v]
|
168
|
+
end
|
169
|
+
when Module, Class
|
170
|
+
if filter.is_a? Class and filter.ancestors.include? Pacer::Wrappers::ElementWrapper
|
171
|
+
self.wrapper = filter
|
172
|
+
else
|
173
|
+
self.extensions << filter
|
174
|
+
end
|
175
|
+
if filter.respond_to? :route_conditions
|
176
|
+
add_filters filter.route_conditions, filter
|
177
|
+
end
|
178
|
+
if filter.respond_to? :route
|
179
|
+
self.route_modules << filter
|
180
|
+
end
|
181
|
+
when Array
|
182
|
+
add_filters(filter, extension)
|
183
|
+
when nil
|
184
|
+
else
|
185
|
+
if filter.respond_to? :wrapper
|
186
|
+
self.wrapper = filter.wrapper
|
187
|
+
if filter.respond_to? :route_conditions
|
188
|
+
add_filters filter.route_conditions, filter
|
189
|
+
end
|
190
|
+
elsif filter.respond_to? :parts
|
191
|
+
self.extensions.concat filter.parts.to_a
|
192
|
+
if filter.respond_to? :route_conditions
|
193
|
+
add_filters filter.route_conditions, filter
|
194
|
+
end
|
195
|
+
else
|
196
|
+
raise "Unknown filter: #{ filter.class }: #{ filter.inspect }"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def add_filters(filters, extension)
|
202
|
+
if filters.is_a? Array
|
203
|
+
filters.each do |filter|
|
204
|
+
add_filter filter, extension
|
205
|
+
end
|
206
|
+
else
|
207
|
+
add_filter filters, extension
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def encode_value(value)
|
212
|
+
value = graph.encode_property(value)
|
213
|
+
if value.respond_to? :to_java
|
214
|
+
jvalue = value.to_java
|
215
|
+
elsif value.respond_to? :to_java_string
|
216
|
+
jvalue = value.to_java_string
|
217
|
+
else
|
218
|
+
jvalue = value
|
219
|
+
end
|
220
|
+
end
|
177
221
|
|
178
222
|
def find_best_index(element_type)
|
179
223
|
return @best_index if @best_index
|
180
224
|
avail = available_indices(element_type)
|
181
225
|
return nil if avail.empty?
|
182
226
|
index_options = []
|
183
|
-
yield avail, index_options if block_given?
|
184
227
|
properties.each do |k, v|
|
185
|
-
if v
|
186
|
-
|
187
|
-
if (idxs = avail["name:#{k}"]).any?
|
188
|
-
if choose_best_index
|
189
|
-
idxs.each do |idx|
|
190
|
-
index_options << [idx.count(k2, encode_value(v2)), [idx, k2, v2], [k, v]]
|
191
|
-
end
|
192
|
-
else
|
193
|
-
@best_index_value = [k, v]
|
194
|
-
return @best_index = [idxs.first, k2, v2]
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
elsif (idxs = (avail["key:#{k}"] + avail[:all])).any?
|
199
|
-
if choose_best_index
|
200
|
-
idxs.each do |idx|
|
201
|
-
index_options << [idx.count(k, encode_value(v)), [idx, k, v], [k, v]]
|
202
|
-
end
|
203
|
-
else
|
204
|
-
@best_index_value = [k, v]
|
205
|
-
return @best_index = [idxs.first, k, v]
|
206
|
-
end
|
207
|
-
else
|
208
|
-
nil
|
228
|
+
if index_for_property(avail, index_options, k, v)
|
229
|
+
return @best_index
|
209
230
|
end
|
210
231
|
end
|
211
232
|
index_options = index_options.sort_by do |a|
|
@@ -223,6 +244,32 @@ module Pacer
|
|
223
244
|
@best_index
|
224
245
|
end
|
225
246
|
|
247
|
+
def index_for_property(avail, index_options, k, v)
|
248
|
+
if v.is_a? Hash
|
249
|
+
if (idxs = avail["name:#{k}"]).any?
|
250
|
+
v.each do |k2, v2|
|
251
|
+
return true if check_index(index_options, idxs, k2.to_s, v2, [k, v])
|
252
|
+
end
|
253
|
+
end
|
254
|
+
false
|
255
|
+
elsif (idxs = (avail["key:#{k}"] + avail[:all])).any?
|
256
|
+
true if check_index(index_options, idxs, k, v, [k, v])
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def check_index(index_options, idxs, k, v, index_value)
|
261
|
+
if choose_best_index
|
262
|
+
idxs.each do |idx|
|
263
|
+
index_options << [idx.count(k, encode_value(v)), [idx, k, v], index_value]
|
264
|
+
end
|
265
|
+
false
|
266
|
+
else
|
267
|
+
@best_index_value = index_value
|
268
|
+
@best_index = [idxs.first, k, v]
|
269
|
+
true
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
226
273
|
def reset_properties
|
227
274
|
@encoded_properties = nil
|
228
275
|
if @best_index_value
|
@@ -243,21 +290,15 @@ module Pacer
|
|
243
290
|
def available_indices(element_type)
|
244
291
|
return @available_indices if @available_indices
|
245
292
|
@available_indices = Hash.new { |h, k| h[k] = [] }
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
@available_indices["key:#{key}"] << index
|
254
|
-
end
|
255
|
-
else
|
256
|
-
@available_indices[:all] << index
|
257
|
-
end
|
258
|
-
else
|
293
|
+
key_index = KeyIndex.new(graph, element_type)
|
294
|
+
graph.key_indices(element_type).each do |key|
|
295
|
+
@available_indices["key:#{key}"] = [key_index]
|
296
|
+
end
|
297
|
+
if search_manual_indices
|
298
|
+
indices.each do |index|
|
299
|
+
next unless graph.index_class? element_type, index.index_class
|
259
300
|
@available_indices["name:#{index.index_name}"] = [index]
|
260
|
-
@available_indices[:all] << index
|
301
|
+
@available_indices[:all] << index
|
261
302
|
end
|
262
303
|
end
|
263
304
|
@available_indices
|
@@ -28,43 +28,48 @@ module Pacer
|
|
28
28
|
filters.is_a? Pacer::Filter::PropertyFilter::Filters
|
29
29
|
end
|
30
30
|
|
31
|
-
def property_filter_before(base,
|
32
|
-
filters = Pacer::Route.edge_filters(
|
31
|
+
def property_filter_before(base, args, block)
|
32
|
+
filters = Pacer::Route.edge_filters(args)
|
33
33
|
filters.blocks = [block] if block
|
34
|
+
args = chain_args(filters)
|
34
35
|
if filters.extensions_only? and base.is_a? Route
|
35
|
-
base.
|
36
|
-
base.add_extensions(filters.extensions)
|
37
|
-
yield base
|
36
|
+
yield base.chain_route(args)
|
38
37
|
elsif filters and filters.any?
|
39
|
-
yield
|
38
|
+
yield base.chain_route(args.merge!(filter: :property, filters: filters))
|
40
39
|
else
|
41
40
|
yield base
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
|
-
def property_filter(base,
|
46
|
-
filters = Pacer::Route.edge_filters(
|
44
|
+
def property_filter(base, args, block)
|
45
|
+
filters = Pacer::Route.edge_filters(args)
|
47
46
|
filters.blocks = [block] if block
|
47
|
+
args = chain_args(filters)
|
48
48
|
if filters.extensions_only? and base.is_a? Route
|
49
|
-
base.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
new(:back => base, :pipe_class => Pacer::Pipes::IdentityPipe)
|
55
|
-
elsif Pacer.edge? base
|
56
|
-
new(:back => base, :pipe_class => Pacer::Pipes::IdentityPipe)
|
49
|
+
base.chain_route(args)
|
50
|
+
elsif filters.any?
|
51
|
+
base.chain_route(args.merge!(filter: :property, filters: filters))
|
52
|
+
elsif base.is_a? Pacer::Wrappers::ElementWrapper
|
53
|
+
base.chain_route({})
|
57
54
|
else
|
58
55
|
base
|
59
56
|
end
|
60
57
|
end
|
58
|
+
|
59
|
+
def chain_args(filters)
|
60
|
+
if filters.wrapper or (filters.extensions and not filters.extensions.empty?)
|
61
|
+
{ extensions: filters.extensions, wrapper: filters.wrapper }
|
62
|
+
else
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
end
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
64
69
|
module Filter
|
65
70
|
module PropertyFilter
|
66
71
|
#import com.tinkerpop.pipes.filter.LabelCollectionFilterPipe
|
67
|
-
import com.tinkerpop.pipes.filter.PropertyFilterPipe
|
72
|
+
import com.tinkerpop.gremlin.pipes.filter.PropertyFilterPipe
|
68
73
|
|
69
74
|
def filters=(f)
|
70
75
|
if f.is_a? Filters
|
@@ -72,8 +77,6 @@ module Pacer
|
|
72
77
|
else
|
73
78
|
@filters = EdgeFilters.new(f)
|
74
79
|
end
|
75
|
-
self.wrapper ||= f.wrapper if f.wrapper
|
76
|
-
add_extensions f.extensions
|
77
80
|
end
|
78
81
|
|
79
82
|
# Return an array of filter options for the current route.
|
@@ -7,7 +7,7 @@ module Pacer
|
|
7
7
|
import com.tinkerpop.pipes.filter.AndFilterPipe
|
8
8
|
import com.tinkerpop.pipes.filter.OrFilterPipe
|
9
9
|
import com.tinkerpop.pipes.filter.ObjectFilterPipe
|
10
|
-
import com.tinkerpop.pipes.transform.PropertyPipe
|
10
|
+
import com.tinkerpop.gremlin.pipes.transform.PropertyPipe
|
11
11
|
import com.tinkerpop.pipes.transform.HasCountPipe
|
12
12
|
NeverPipe = Pacer::Pipes::NeverPipe
|
13
13
|
IdentityPipe = Pacer::Pipes::IdentityPipe
|
@@ -34,11 +34,11 @@ module Pacer
|
|
34
34
|
'>=' => FilterPipe::Filter::LESS_THAN_EQUAL
|
35
35
|
)
|
36
36
|
|
37
|
-
|
37
|
+
COMPARATORS = %w[ == != > < >= <= ]
|
38
38
|
METHODS = %w[ + - * / % ]
|
39
|
-
|
39
|
+
REGEX_COMPARATORS = %w[ =~ !~ ]
|
40
40
|
|
41
|
-
VALID_OPERATIONS =
|
41
|
+
VALID_OPERATIONS = COMPARATORS + METHODS # + REGEX_COMPARATORS
|
42
42
|
|
43
43
|
class Pipe
|
44
44
|
def initialize(pipe, *args)
|
@@ -118,7 +118,7 @@ module Pacer
|
|
118
118
|
# TODO: support regex matches
|
119
119
|
|
120
120
|
raise "Operation not supported: #{ name }" unless VALID_OPERATIONS.include? name
|
121
|
-
if
|
121
|
+
if COMPARATORS.include? name
|
122
122
|
if a.is_a? Value and b.is_a? Value
|
123
123
|
if a.value.send name, b.value
|
124
124
|
Pipe.new IdentityPipe
|
@@ -139,11 +139,23 @@ module Pacer
|
|
139
139
|
Pipe.new CrossProductTransformPipe, name, a, b
|
140
140
|
end
|
141
141
|
end
|
142
|
-
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def negate(pipe)
|
145
|
+
Pipe.new(Pipeline, pipe, Pipe.new(HasCountPipe, -1, 0), Pipe.new(ObjectFilterPipe, true, Filters['==']))
|
146
|
+
end
|
147
|
+
|
148
|
+
def comparable_pipe(pipe)
|
149
|
+
if pipe.pipe == PropertyPipe
|
150
|
+
build_comparison(pipe, Value.new(nil), '!=')
|
151
|
+
else
|
152
|
+
pipe
|
153
|
+
end
|
154
|
+
end
|
143
155
|
|
144
156
|
def visitAndNode(node)
|
145
|
-
a = node.first_node.accept(self)
|
146
|
-
b = node.second_node.accept(self)
|
157
|
+
a = comparable_pipe node.first_node.accept(self)
|
158
|
+
b = comparable_pipe node.second_node.accept(self)
|
147
159
|
|
148
160
|
if a.pipe == AndFilterPipe and b.pipe == AndFilterPipe
|
149
161
|
Pipe.new AndFilterPipe, *a.args, *b.args
|
@@ -154,11 +166,11 @@ module Pacer
|
|
154
166
|
else
|
155
167
|
Pipe.new AndFilterPipe, a, b
|
156
168
|
end
|
157
|
-
end
|
169
|
+
end
|
158
170
|
|
159
171
|
def visitArrayNode(node)
|
160
172
|
Value.new Value.new(node.child_nodes.map { |n| n.accept self }).values!
|
161
|
-
end
|
173
|
+
end
|
162
174
|
|
163
175
|
def visitBignumNode(node)
|
164
176
|
Value.new node.value.to_s
|
@@ -174,12 +186,16 @@ module Pacer
|
|
174
186
|
if a.is_a? Value
|
175
187
|
Value.new a.value.send(a.name)
|
176
188
|
elsif a.pipe == PropertyPipe
|
177
|
-
|
189
|
+
if node.name == '!'
|
190
|
+
negate(comparable_pipe(a))
|
191
|
+
else
|
192
|
+
Pipe.new(UnaryTransformPipe, node.name, a)
|
193
|
+
end
|
178
194
|
else
|
179
195
|
case node.name
|
180
196
|
when '!'
|
181
197
|
# Special case for "a == 1 and not (b == 1)", etc.
|
182
|
-
|
198
|
+
negate a
|
183
199
|
else
|
184
200
|
raise 'not sure'
|
185
201
|
end
|
@@ -189,11 +205,11 @@ module Pacer
|
|
189
205
|
|
190
206
|
def visitFalseNode(node)
|
191
207
|
Pipe.new NeverPipe
|
192
|
-
end
|
208
|
+
end
|
193
209
|
|
194
210
|
def visitFixnumNode(node)
|
195
211
|
Value.new node.value
|
196
|
-
end
|
212
|
+
end
|
197
213
|
|
198
214
|
def visitFloatNode(node)
|
199
215
|
Value.new node.value
|
@@ -207,7 +223,7 @@ module Pacer
|
|
207
223
|
a = Pipe.new PropertyPipe, node.name
|
208
224
|
b = node.value_node.accept(self)
|
209
225
|
build_comparison(a, b, '==')
|
210
|
-
end
|
226
|
+
end
|
211
227
|
|
212
228
|
def visitLocalVarNode(node)
|
213
229
|
Pipe.new PropertyPipe, node.name
|
@@ -215,15 +231,16 @@ module Pacer
|
|
215
231
|
|
216
232
|
def visitNewlineNode(node)
|
217
233
|
node.next_node.accept(self)
|
218
|
-
end
|
234
|
+
end
|
219
235
|
|
220
236
|
def visitNilNode(node)
|
221
237
|
Value.new nil
|
222
|
-
end
|
238
|
+
end
|
223
239
|
|
224
240
|
def visitOrNode(node)
|
225
|
-
a = node.first_node.accept(self)
|
226
|
-
b = node.second_node.accept(self)
|
241
|
+
a = comparable_pipe node.first_node.accept(self)
|
242
|
+
b = comparable_pipe node.second_node.accept(self)
|
243
|
+
|
227
244
|
if a.pipe == OrFilterPipe and b.pipe == OrFilterPipe
|
228
245
|
Pipe.new OrFilterPipe, *a.args, *b.args
|
229
246
|
elsif a.pipe == OrFilterPipe
|
@@ -233,7 +250,7 @@ module Pacer
|
|
233
250
|
else
|
234
251
|
Pipe.new OrFilterPipe, a, b
|
235
252
|
end
|
236
|
-
end
|
253
|
+
end
|
237
254
|
|
238
255
|
def visitRootNode(node)
|
239
256
|
pipe = node.body_node.accept self
|
@@ -246,25 +263,29 @@ module Pacer
|
|
246
263
|
Pipe.new NeverPipe
|
247
264
|
end
|
248
265
|
else
|
249
|
-
Pipe.new AndFilterPipe, pipe
|
266
|
+
Pipe.new AndFilterPipe, comparable_pipe(pipe)
|
250
267
|
end
|
251
|
-
end
|
268
|
+
end
|
252
269
|
|
253
270
|
def visitStrNode(node)
|
254
271
|
Value.new node.value
|
255
|
-
end
|
272
|
+
end
|
256
273
|
|
257
274
|
def visitSymbolNode(node)
|
258
275
|
Value.new values.fetch(node.name.to_sym, node.name.to_sym)
|
259
|
-
end
|
276
|
+
end
|
260
277
|
|
261
278
|
def visitTrueNode(node)
|
262
279
|
Pipe.new IdentityPipe
|
263
|
-
end
|
280
|
+
end
|
264
281
|
|
265
282
|
def visitVCallNode(node)
|
266
283
|
Pipe.new PropertyPipe, node.name
|
267
|
-
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def visitXStrNode(node)
|
287
|
+
Pipe.new PropertyPipe, node.value
|
288
|
+
end
|
268
289
|
|
269
290
|
def visitYieldNode(node)
|
270
291
|
block = node.args_node.child_nodes.first.accept(self)
|
@@ -1,10 +1,27 @@
|
|
1
1
|
require 'pacer/filter/where_filter/node_visitor'
|
2
|
+
require 'jruby' # for JRuby.parse
|
2
3
|
|
3
4
|
module Pacer
|
4
5
|
module Routes
|
5
6
|
module RouteOperations
|
6
|
-
def where(str, values = {})
|
7
|
-
|
7
|
+
def where(str, values = {}, *more, &block)
|
8
|
+
if str.is_a? String or str.is_a? Symbol
|
9
|
+
if str !~ /\A\s*\Z/
|
10
|
+
chain_route :filter => :where, :where_statement => str.to_s, :values => values
|
11
|
+
else
|
12
|
+
self
|
13
|
+
end
|
14
|
+
else
|
15
|
+
filter(str, values, *more, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def unless(str, values = {})
|
20
|
+
if str and str !~ /\A\s*\Z/
|
21
|
+
where "not (#{str})", values
|
22
|
+
else
|
23
|
+
self
|
24
|
+
end
|
8
25
|
end
|
9
26
|
end
|
10
27
|
end
|
@@ -24,7 +41,11 @@ module Pacer
|
|
24
41
|
end
|
25
42
|
|
26
43
|
def intermediate
|
27
|
-
|
44
|
+
encoded_values = {}
|
45
|
+
if values
|
46
|
+
values.each { |k, v| encoded_values[k.to_sym] = graph.encode_property(v) }
|
47
|
+
end
|
48
|
+
@intermediate ||= parsed.accept(NodeVisitor.new(self, encoded_values))
|
28
49
|
end
|
29
50
|
|
30
51
|
def build!
|