pacer 0.9.1.1-java → 1.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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!
|