neo4j-core 2.1.0-java → 2.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +0 -10
  2. data/README.rdoc +2 -130
  3. data/config/neo4j/config.yml~ +102 -0
  4. data/lib/db/active_tx_log +1 -0
  5. data/lib/db/index/lucene-store.db +0 -0
  6. data/lib/db/index/lucene.log.active +0 -0
  7. data/lib/db/index/lucene.log.v0 +0 -0
  8. data/lib/db/messages.log +285 -0
  9. data/lib/db/neostore +0 -0
  10. data/lib/db/neostore.id +0 -0
  11. data/lib/db/neostore.nodestore.db +1 -0
  12. data/lib/db/neostore.nodestore.db.id +0 -0
  13. data/lib/db/neostore.propertystore.db +1 -0
  14. data/lib/db/neostore.propertystore.db.arrays +0 -0
  15. data/lib/db/neostore.propertystore.db.arrays.id +0 -0
  16. data/lib/db/neostore.propertystore.db.id +0 -0
  17. data/lib/db/neostore.propertystore.db.index +1 -0
  18. data/lib/db/neostore.propertystore.db.index.id +0 -0
  19. data/lib/db/neostore.propertystore.db.index.keys +0 -0
  20. data/lib/db/neostore.propertystore.db.index.keys.id +0 -0
  21. data/lib/db/neostore.propertystore.db.strings +0 -0
  22. data/lib/db/neostore.propertystore.db.strings.id +0 -0
  23. data/lib/db/neostore.relationshipstore.db +1 -0
  24. data/lib/db/neostore.relationshipstore.db.id +0 -0
  25. data/lib/db/neostore.relationshiptypestore.db +1 -0
  26. data/lib/db/neostore.relationshiptypestore.db.id +0 -0
  27. data/lib/db/neostore.relationshiptypestore.db.names +0 -0
  28. data/lib/db/neostore.relationshiptypestore.db.names.id +0 -0
  29. data/lib/db/nioneo_logical.log.active +0 -0
  30. data/lib/db/nioneo_logical.log.v0 +0 -0
  31. data/lib/db/tm_tx_log.1 +0 -0
  32. data/lib/neo4j-core.rb +4 -4
  33. data/lib/neo4j-core/database.rb +1 -0
  34. data/lib/neo4j-core/index/index_config.rb +1 -1
  35. data/lib/neo4j-core/property/property.rb +11 -0
  36. data/lib/neo4j-core/relationship/class_methods.rb +1 -3
  37. data/lib/neo4j-core/traversal/traverser.rb +19 -29
  38. data/lib/neo4j-core/version.rb +1 -1
  39. data/lib/neo4j-core/version.rb~ +5 -0
  40. data/lib/neo4j/config.rb +2 -2
  41. data/lib/neo4j/config.rb~ +136 -0
  42. data/lib/neo4j/neo4j.rb +3 -3
  43. data/neo4j-core.gemspec +1 -0
  44. metadata +81 -6
  45. data/lib/neo4j-core/cypher/cypher.rb +0 -1033
  46. data/lib/neo4j-core/cypher/result_wrapper.rb +0 -48
  47. data/lib/neo4j/cypher.rb +0 -180
@@ -1,1033 +0,0 @@
1
- module Neo4j
2
- module Core
3
-
4
- # This module contains a number of mixins and classes used by the neo4j.rb cypher DSL.
5
- # The Cypher DSL is evaluated in the context of {Neo4j::Cypher} which contains a number of methods (e.g. {Neo4j::Cypher#node})
6
- # which returns classes from this module.
7
- module Cypher
8
-
9
- module MathFunctions
10
- def abs(value=nil)
11
- _add_math_func(:abs, value)
12
- end
13
-
14
- def sqrt(value=nil)
15
- _add_math_func(:sqrt, value)
16
- end
17
-
18
- def round(value=nil)
19
- _add_math_func(:round, value)
20
- end
21
-
22
- def sign(value=nil)
23
- _add_math_func(:sign, value)
24
- end
25
-
26
- # @private
27
- def _add_math_func(name, value=nil)
28
- value ||= self.respond_to?(:var_name) ? self.var_name : to_s
29
- expressions.delete(self)
30
- Property.new(expressions, nil, name).to_function!(value)
31
- end
32
- end
33
-
34
- module MathOperator
35
- def -(other)
36
- ExprOp.new(self, other, '-')
37
- end
38
-
39
- def +(other)
40
- ExprOp.new(self, other, '+')
41
- end
42
- end
43
-
44
- module Comparable
45
- def <(other)
46
- ExprOp.new(self, other, '<')
47
- end
48
-
49
- def <=(other)
50
- ExprOp.new(self, other, '<=')
51
- end
52
-
53
- def =~(other)
54
- ExprOp.new(self, other, '=~')
55
- end
56
-
57
- def >(other)
58
- ExprOp.new(self, other, '>')
59
- end
60
-
61
- def >=(other)
62
- ExprOp.new(self, other, '>=')
63
- end
64
-
65
- ## Only in 1.9
66
- if RUBY_VERSION > "1.9.0"
67
- eval %{
68
- def !=(other)
69
- other.is_a?(String) ? ExprOp.new(self, other, "!=") : super
70
- end }
71
- end
72
-
73
- def ==(other)
74
- if other.is_a?(Fixnum) || other.is_a?(String) || other.is_a?(Regexp)
75
- ExprOp.new(self, other, "=")
76
- else
77
- super
78
- end
79
- end
80
- end
81
-
82
- module PredicateMethods
83
- def all?(&block)
84
- self.respond_to?(:iterable)
85
- Predicate.new(expressions, :op => 'all', :clause => :where, :input => input, :iterable => iterable, :predicate_block => block)
86
- end
87
-
88
- def extract(&block)
89
- Predicate.new(expressions, :op => 'extract', :clause => :return, :input => input, :iterable => iterable, :predicate_block => block)
90
- end
91
-
92
- def filter(&block)
93
- Predicate.new(expressions, :op => 'filter', :clause => :return, :input => input, :iterable => iterable, :predicate_block => block)
94
- end
95
-
96
- def any?(&block)
97
- Predicate.new(@expressions, :op => 'any', :clause => :where, :input => input, :iterable => iterable, :predicate_block => block)
98
- end
99
-
100
- def none?(&block)
101
- Predicate.new(@expressions, :op => 'none', :clause => :where, :input => input, :iterable => iterable, :predicate_block => block)
102
- end
103
-
104
- def single?(&block)
105
- Predicate.new(@expressions, :op => 'single', :clause => :where, :input => input, :iterable => iterable, :predicate_block => block)
106
- end
107
-
108
- end
109
-
110
- module Variable
111
- attr_accessor :return_method
112
-
113
- def distinct
114
- self.return_method = {:name => 'distinct', :bracket => false}
115
- self
116
- end
117
-
118
- def [](prop_name)
119
- Property.new(expressions, self, prop_name)
120
- end
121
-
122
- def as(v)
123
- @var_name = v
124
- self
125
- end
126
-
127
- # generates a <tt>ID</tt> cypher fragment.
128
- def neo_id
129
- Property.new(@expressions, self, 'ID').to_function!
130
- end
131
-
132
- # generates a <tt>has</tt> cypher fragment.
133
- def property?(p)
134
- p = Property.new(expressions, self, p)
135
- p.binary_operator("has")
136
- end
137
-
138
- # generates a <tt>is null</tt> cypher fragment.
139
- def exist?
140
- p = Property.new(expressions, self, p)
141
- p.binary_operator("", " is null")
142
- end
143
-
144
- # Can be used instead of [_classname] == klass
145
- def is_a?(klass)
146
- return super if klass.class != Class || !klass.respond_to?(:_load_wrapper)
147
- self[:_classname] == klass.to_s
148
- end
149
-
150
- def count
151
- #expressions.delete(self)
152
- ExprOp.new(self, nil, 'count')
153
- end
154
- end
155
-
156
- module Matchable
157
-
158
- def where(&block)
159
- x = block.call(self)
160
- expressions.delete(x)
161
- ExprOp.new(x, nil, "").binary!
162
- self
163
- end
164
-
165
- def where_not(&block)
166
- x = block.call(self)
167
- expressions.delete(x)
168
- ExprOp.new(x, nil, "not").binary!
169
- self
170
- end
171
-
172
-
173
- # This operator means related to, without regard to type or direction.
174
- # @param [Symbol, #var_name] other either a node (Symbol, #var_name)
175
- # @return [MatchRelLeft, MatchNode]
176
- def <=>(other)
177
- MatchNode.new(self, other, expressions, :both)
178
- end
179
-
180
- # This operator means outgoing related to
181
- # @param [Symbol, #var_name, String] other the relationship
182
- # @return [MatchRelLeft, MatchNode]
183
- def >(other)
184
- MatchRelLeft.new(self, other, expressions, :outgoing)
185
- end
186
-
187
- # This operator means any direction related to
188
- # @param (see #>)
189
- # @return [MatchRelLeft, MatchNode]
190
- def -(other)
191
- MatchRelLeft.new(self, other, expressions, :both)
192
- end
193
-
194
- # This operator means incoming related to
195
- # @param (see #>)
196
- # @return [MatchRelLeft, MatchNode]
197
- def <(other)
198
- MatchRelLeft.new(self, other, expressions, :incoming)
199
- end
200
-
201
- # Outgoing relationship to other node
202
- # @param [Symbol, #var_name] other either a node (Symbol, #var_name)
203
- # @return [MatchRelLeft, MatchNode]
204
- def >>(other)
205
- MatchNode.new(self, other, expressions, :outgoing)
206
- end
207
-
208
- def outgoing(rel_type)
209
- node = NodeVar.new(@expressions, @variables)
210
- MatchRelLeft.new(self, ":`#{rel_type}`", expressions, :outgoing) > node
211
- node
212
- end
213
-
214
- def incoming(rel_type)
215
- node = NodeVar.new(@expressions, @variables)
216
- MatchRelLeft.new(self, ":`#{rel_type}`", expressions, :incoming) < node
217
- node
218
- end
219
-
220
- def both(rel_type)
221
- node = NodeVar.new(@expressions, @variables)
222
- MatchRelLeft.new(self, ":`#{rel_type}`", expressions, :both) < node
223
- node
224
- end
225
-
226
- # Incoming relationship to other node
227
- # @param [Symbol, #var_name] other either a node (Symbol, #var_name)
228
- # @return [MatchRelLeft, MatchNode]
229
- def <<(other)
230
- MatchNode.new(self, other, expressions, :incoming)
231
- end
232
- end
233
-
234
- class Expression
235
- attr_reader :expressions
236
- attr_accessor :separator, :clause
237
-
238
- def initialize(expressions, clause)
239
- @clause = clause
240
- @expressions = expressions
241
- insert_last(clause)
242
- @separator = ","
243
- end
244
-
245
- def insert_last(clause)
246
- curr_clause = clause
247
- while (i = @expressions.reverse.index { |e| e.clause == curr_clause }).nil? && curr_clause != :start
248
- curr_clause = prev_clause(curr_clause)
249
- end
250
-
251
- if i.nil?
252
- @expressions << self
253
- else
254
- pos = @expressions.size - i
255
- @expressions.insert(pos, self)
256
- end
257
- end
258
-
259
- def prev_clause(clause)
260
- {:limit => :skip, :skip => :order_by, :order_by => :return, :return => :where, :where => :match, :match => :start}[clause]
261
- end
262
-
263
- def prefixes
264
- {:start => "START", :where => " WHERE", :match => " MATCH", :return => " RETURN", :order_by => " ORDER BY", :skip => " SKIP", :limit => " LIMIT"}
265
- end
266
-
267
- def prefix
268
- prefixes[clause]
269
- end
270
-
271
- def valid?
272
- true
273
- end
274
-
275
- end
276
-
277
- # A property is returned from a Variable by using the [] operator.
278
- #
279
- # It has a number of useful method like
280
- # <tt>count</tt>, <tt>sum</tt>, <tt>avg</tt>, <tt>min</tt>, <tt>max</tt>, <tt>collect</tt>, <tt>head</tt>, <tt>last</tt>, <tt>tail</tt>,
281
- #
282
- # @example
283
- # n=node(2, 3, 4); n[:name].collect
284
- # # same as START n0=node(2,3,4) RETURN collect(n0.property)
285
- class Property
286
- # @private
287
- attr_reader :expressions, :var_name, :var_expr
288
- include Comparable
289
- include MathOperator
290
- include MathFunctions
291
- include PredicateMethods
292
-
293
- def initialize(expressions, var_expr, prop_name)
294
- @var_expr = var_expr
295
- @var = var_expr.respond_to?(:var_name) ? var_expr.var_name : var_expr
296
- @expressions = expressions
297
- @prop_name = prop_name
298
- @var_name = @prop_name ? "#{@var.to_s}.#{@prop_name}" : @var.to_s
299
- end
300
-
301
- # @private
302
- def to_function!(var = @var.to_s)
303
- @var_name = "#{@prop_name}(#{var})"
304
- self
305
- end
306
-
307
- # Make it possible to rename a property with a different name (AS)
308
- def as(new_name)
309
- @var_name = "#{@var_name} AS #{new_name}"
310
- end
311
-
312
- # required by the Predicate Methods Module
313
- # @see PredicateMethods
314
- # @private
315
- def iterable
316
- var_name
317
- end
318
-
319
- def input
320
- self
321
- end
322
-
323
- # @private
324
- def in?(values)
325
- binary_operator("", " IN [#{values.map { |x| %Q["#{x}"] }.join(',')}]")
326
- end
327
-
328
- # Only return distinct values/nodes/rels/paths
329
- def distinct
330
- @var_name = "distinct #{@var_name}"
331
- self
332
- end
333
-
334
- def length
335
- @prop_name = "length"
336
- to_function!
337
- self
338
- end
339
-
340
- %w[count sum avg min max collect head last tail].each do |meth_name|
341
- define_method(meth_name) do
342
- function(meth_name.to_s)
343
- end
344
- end
345
-
346
- # @private
347
- def function(func_name_pre, func_name_post = "")
348
- ExprOp.new(self, nil, func_name_pre, func_name_post)
349
- end
350
-
351
- # @private
352
- def binary_operator(op, post_fix = "")
353
- ExprOp.new(self, nil, op, post_fix).binary!
354
- end
355
- end
356
-
357
- class Start < Expression
358
- # @private
359
- attr_reader :var_name
360
- include Variable
361
- include Matchable
362
-
363
- def initialize(var_name, expressions)
364
- @var_name = "#{var_name}#{expressions.size}"
365
- super(expressions, :start)
366
- end
367
-
368
- end
369
-
370
- # Can be created from a <tt>node</tt> dsl method.
371
- class StartNode < Start
372
- # @private
373
- attr_reader :nodes
374
-
375
- def initialize(nodes, expressions)
376
- super("n", expressions)
377
-
378
- @nodes = nodes.map { |n| n.respond_to?(:neo_id) ? n.neo_id : n }
379
- end
380
-
381
- def to_s
382
- "#{var_name}=node(#{nodes.join(',')})"
383
- end
384
- end
385
-
386
-
387
- # Can be created from a <tt>rel</tt> dsl method.
388
- class StartRel < Start
389
- # @private
390
- attr_reader :rels
391
-
392
- def initialize(rels, expressions)
393
- super("r", expressions)
394
- @rels = rels.map { |n| n.respond_to?(:neo_id) ? n.neo_id : n }
395
- end
396
-
397
- def to_s
398
- "#{var_name}=relationship(#{rels.join(',')})"
399
- end
400
- end
401
-
402
- class NodeQuery < Start
403
- attr_reader :index_name, :query
404
-
405
- def initialize(index_class, query, index_type, expressions)
406
- super("n", expressions)
407
- @index_name = index_class.index_name_for_type(index_type)
408
- @query = query
409
- end
410
-
411
- def to_s
412
- "#{var_name}=node:#{index_name}(#{query})"
413
- end
414
- end
415
-
416
- class NodeLookup < Start
417
- attr_reader :index_name, :query
418
-
419
- def initialize(index_class, key, value, expressions)
420
- super("n", expressions)
421
- index_type = index_class.index_type(key.to_s)
422
- raise "No index on #{index_class} property #{key}" unless index_type
423
- @index_name = index_class.index_name_for_type(index_type)
424
- @query = %Q[#{key}="#{value}"]
425
- end
426
-
427
- def to_s
428
- %Q[#{var_name}=node:#{index_name}(#{query})]
429
- end
430
-
431
- end
432
-
433
- # The return statement in the cypher query
434
- class Return < Expression
435
- attr_reader :var_name
436
-
437
- def initialize(name_or_ref, expressions, opts = {})
438
- super(expressions, :return)
439
- @name_or_ref = name_or_ref
440
- @name_or_ref.referenced! if @name_or_ref.respond_to?(:referenced!)
441
- @var_name = @name_or_ref.respond_to?(:var_name) ? @name_or_ref.var_name : @name_or_ref.to_s
442
- opts.each_pair { |k, v| self.send(k, v) }
443
- end
444
-
445
- # @private
446
- def return_method
447
- @name_or_ref.respond_to?(:return_method) && @name_or_ref.return_method
448
- end
449
-
450
- # @private
451
- def as_return_method
452
- if return_method[:bracket]
453
- "#{return_method[:name]}(#@var_name)"
454
- else
455
- "#{return_method[:name]} #@var_name"
456
- end
457
- end
458
-
459
- # Specifies an <tt>ORDER BY</tt> cypher query
460
- # @param [Property] props the properties which should be sorted
461
- # @return self
462
- def asc(*props)
463
- @order_by ||= OrderBy.new(expressions)
464
- expressions.delete(props.first)
465
- @order_by.asc(props)
466
- self
467
- end
468
-
469
- # Specifies an <tt>ORDER BY</tt> cypher query
470
- # @param [Property] props the properties which should be sorted
471
- # @return self
472
- def desc(*props)
473
- @order_by ||= OrderBy.new(expressions)
474
- expressions.delete(props.first)
475
- @order_by.desc(props)
476
- self
477
- end
478
-
479
- # Creates a <tt>SKIP</tt> cypher clause
480
- # @param [Fixnum] val the number of entries to skip
481
- # @return self
482
- def skip(val)
483
- Skip.new(expressions, val)
484
- self
485
- end
486
-
487
- # Creates a <tt>LIMIT</tt> cypher clause
488
- # @param [Fixnum] val the number of entries to limit
489
- # @return self
490
- def limit(val)
491
- Limit.new(expressions, val)
492
- self
493
- end
494
-
495
- def to_s
496
- return_method ? as_return_method : var_name.to_s
497
- end
498
- end
499
-
500
- # Can be used to skip result from a return clause
501
- class Skip < Expression
502
- def initialize(expressions, value)
503
- super(expressions, :skip)
504
- @value = value
505
- end
506
-
507
- def to_s
508
- @value
509
- end
510
- end
511
-
512
- # Can be used to limit result from a return clause
513
- class Limit < Expression
514
- def initialize(expressions, value)
515
- super(expressions, :limit)
516
- @value = value
517
- end
518
-
519
- def to_s
520
- @value
521
- end
522
- end
523
-
524
- class OrderBy < Expression
525
- def initialize(expressions)
526
- super(expressions, :order_by)
527
- @orders = []
528
- end
529
-
530
- def asc(props)
531
- @orders << [:asc, props]
532
- end
533
-
534
- def desc(props)
535
- @orders << [:desc, props]
536
- end
537
-
538
- def to_s
539
- @orders.map do |pair|
540
- if pair[0] == :asc
541
- pair[1].map(&:var_name).join(', ')
542
- else
543
- pair[1].map(&:var_name).join(', ') + " DESC"
544
- end
545
- end.join(', ')
546
- end
547
- end
548
-
549
- # Created from a node's match operator like >> or <.
550
- class Match < Expression
551
- # @private
552
- attr_reader :dir, :expressions, :left, :right, :var_name, :dir_op
553
- # @private
554
- attr_accessor :algorithm, :next, :prev
555
- include Variable
556
-
557
- def initialize(left, right, expressions, dir, dir_op)
558
- super(expressions, :match)
559
- @var_name = "m#{expressions.size}"
560
- @dir = dir
561
- @dir_op = dir_op
562
- @prev = left if left.is_a?(Match)
563
- @left = left
564
- @right = right
565
- end
566
-
567
-
568
- # Generates a <tt>x in nodes(m3)</tt> cypher expression.
569
- #
570
- # @example
571
- # p.nodes.all? { |x| x[:age] > 30 }
572
- def nodes
573
- Entities.new(@expressions, "nodes", self)
574
- end
575
-
576
- # Generates a <tt>x in relationships(m3)</tt> cypher expression.
577
- #
578
- # @example
579
- # p.relationships.all? { |x| x[:age] > 30 }
580
- def rels
581
- Entities.new(@expressions, "relationships", self)
582
- end
583
-
584
- # returns the length of the path
585
- def length
586
- self.return_method = {:name => 'length', :bracket => true}
587
- self
588
- end
589
-
590
- # @private
591
- def find_match_start
592
- c = self
593
- while (c.prev) do
594
- c = c.prev
595
- end
596
- c
597
- end
598
-
599
- # @private
600
- def left_var_name
601
- @left.respond_to?(:var_name) ? @left.var_name : @left.to_s
602
- end
603
-
604
- # @private
605
- def right_var_name
606
- @right.respond_to?(:var_name) ? @right.var_name : @right.to_s
607
- end
608
-
609
- # @private
610
- def right_expr
611
- c = @right
612
- r = while (c)
613
- break c.var_expr if c.respond_to?(:var_expr)
614
- c = c.respond_to?(:left_expr) && c.left_expr
615
- end || @right
616
-
617
- r.respond_to?(:expr) ? r.expr : right_var_name
618
- end
619
-
620
- # @private
621
- def referenced!
622
- @referenced = true
623
- end
624
-
625
- # @private
626
- def referenced?
627
- !!@referenced
628
- end
629
-
630
- # @private
631
- def to_s
632
- curr = find_match_start
633
- result = (referenced? || curr.referenced?) ? "#{var_name} = " : ""
634
- result << (algorithm ? "#{algorithm}(" : "")
635
- begin
636
- result << curr.expr
637
- end while (curr = curr.next)
638
- result << ")" if algorithm
639
- result
640
- end
641
- end
642
-
643
- # The left part of a match clause, e.g. node < rel(':friends')
644
- # Can return {MatchRelRight} using a match operator method.
645
- class MatchRelLeft < Match
646
- def initialize(left, right, expressions, dir)
647
- super(left, right, expressions, dir, dir == :incoming ? '<-' : '-')
648
- end
649
-
650
- # @param [Symbol,NodeVar,String] other part of the match cypher statement.
651
- # @return [MatchRelRight] the right part of an relationship cypher query.
652
- def >(other)
653
- expressions.delete(self)
654
- self.next = MatchRelRight.new(self, other, expressions, :outgoing)
655
- end
656
-
657
- # @see #>
658
- # @return (see #>)
659
- def <(other)
660
- expressions.delete(self)
661
- self.next = MatchRelRight.new(self, other, expressions, :incoming)
662
- end
663
-
664
- # @see #>
665
- # @return (see #>)
666
- def -(other)
667
- expressions.delete(self)
668
- self.next = MatchRelRight.new(self, other, expressions, :both)
669
- end
670
-
671
- # @return [String] a cypher string for this match.
672
- def expr
673
- if prev
674
- # we have chained more then one relationships in a match expression
675
- "#{dir_op}[#{right_expr}]"
676
- else
677
- # the right is an relationship and could be an expressions, e.g "r?"
678
- "(#{left_var_name})#{dir_op}[#{right_expr}]"
679
- end
680
- end
681
- end
682
-
683
- class MatchRelRight < Match
684
- # @param left the left part of the query
685
- # @param [Symbol,NodeVar,String] right part of the match cypher statement.
686
- def initialize(left, right, expressions, dir)
687
- super(left, right, expressions, dir, dir == :outgoing ? '->' : '-')
688
- end
689
-
690
- # @param [Symbol,NodeVar,String] other part of the match cypher statement.
691
- # @return [MatchRelLeft] the right part of an relationship cypher query.
692
- def >(other)
693
- expressions.delete(self)
694
- self.next = MatchRelLeft.new(self, other, expressions, :outgoing)
695
- end
696
-
697
- # @see #>
698
- # @return (see #>)
699
- def <(other)
700
- expressions.delete(self)
701
- self.next = MatchRelLeft.new(self, other, expressions, :incoming)
702
- end
703
-
704
- # @see #>
705
- # @return (see #>)
706
- def -(other)
707
- expressions.delete(self)
708
- self.next = MatchRelLeft.new(self, other, expressions, :both)
709
- end
710
-
711
- def <<(other)
712
- expressions.delete(self)
713
- self.next = MatchNode.new(self, other, expressions, :incoming)
714
- end
715
-
716
- def >>(other)
717
- expressions.delete(self)
718
- self.next = MatchNode.new(self, other, expressions, :outgoing)
719
- end
720
-
721
- # @return [String] a cypher string for this match.
722
- def expr
723
- "#{dir_op}(#{right_expr})"
724
- end
725
-
726
- # negate this match
727
- def not
728
- expressions.delete(self)
729
- ExprOp.new(left, nil, "not").binary!
730
- end
731
-
732
- if RUBY_VERSION > "1.9.0"
733
- eval %{
734
- def !
735
- expressions.delete(self)
736
- ExprOp.new(left, nil, "not").binary!
737
- end
738
- }
739
- end
740
-
741
- end
742
-
743
- # The right part of a match clause (node_b), e.g. node_a > rel(':friends') > node_b
744
- #
745
- class MatchNode < Match
746
- attr_reader :dir_op
747
-
748
- def initialize(left, right, expressions, dir)
749
- dir_op = case dir
750
- when :outgoing then
751
- "-->"
752
- when :incoming then
753
- "<--"
754
- when :both then
755
- "--"
756
- end
757
- super(left, right, expressions, dir, dir_op)
758
- end
759
-
760
- # @return [String] a cypher string for this match.
761
- def expr
762
- if prev
763
- # we have chained more then one relationships in a match expression
764
- "#{dir_op}(#{right_expr})"
765
- else
766
- # the right is an relationship and could be an expressions, e.g "r?"
767
- "(#{left_var_name})#{dir_op}(#{right_expr})"
768
- end
769
- end
770
-
771
- def <<(other)
772
- expressions.delete(self)
773
- self.next = MatchNode.new(self, other, expressions, :incoming)
774
- end
775
-
776
- def >>(other)
777
- expressions.delete(self)
778
- self.next = MatchNode.new(self, other, expressions, :outgoing)
779
- end
780
-
781
- # @param [Symbol,NodeVar,String] other part of the match cypher statement.
782
- # @return [MatchRelRight] the right part of an relationship cypher query.
783
- def >(other)
784
- expressions.delete(self)
785
- self.next = MatchRelLeft.new(self, other, expressions, :outgoing)
786
- end
787
-
788
- # @see #>
789
- # @return (see #>)
790
- def <(other)
791
- expressions.delete(self)
792
- self.next = MatchRelLeft.new(self, other, expressions, :incoming)
793
- end
794
-
795
- # @see #>
796
- # @return (see #>)
797
- def -(other)
798
- expressions.delete(self)
799
- self.next = MatchRelLeft.new(self, other, expressions, :both)
800
- end
801
-
802
- end
803
-
804
- # Represents an unbound node variable used in match statements
805
- class NodeVar
806
- include Variable
807
- include Matchable
808
-
809
- # @return the name of the variable
810
- attr_reader :var_name
811
- attr_reader :expressions
812
-
813
- def initialize(expressions, variables)
814
- variables ||= []
815
- @var_name = "v#{variables.size}"
816
- variables << self
817
- @variables = variables
818
- @expressions = expressions
819
- end
820
-
821
- # @return [String] a cypher string for this node variable
822
- def to_s
823
- var_name
824
- end
825
-
826
- # @private
827
- def expr
828
- to_s
829
- end
830
-
831
- end
832
-
833
- # represent an unbound relationship variable used in match,where,return statement
834
- class RelVar
835
- include Variable
836
-
837
- attr_reader :var_name, :expr, :expressions
838
-
839
- def initialize(expressions, variables, expr)
840
- variables << self
841
- @expr = expr
842
- @expressions = expressions
843
- guess = expr ? /([[:alpha:]_]*)/.match(expr)[1] : ""
844
- @auto_var_name = "v#{variables.size}"
845
- @var_name = guess.empty? ? @auto_var_name : guess
846
- end
847
-
848
- def rel_type
849
- Property.new(@expressions, self, 'type').to_function!
850
- end
851
-
852
- def [](p)
853
- if @expr.to_s[0..0] == ':'
854
- @var_name = @auto_var_name
855
- @expr = "#{@var_name}#{@expr}"
856
- end
857
- super
858
- end
859
-
860
- # @return [String] a cypher string for this relationship variable
861
- def to_s
862
- var_name
863
- end
864
-
865
- end
866
-
867
- class ExprOp < Expression
868
- attr_reader :left, :right, :op, :neg, :post_fix, :left_expr, :right_expr
869
- include MathFunctions
870
-
871
-
872
- def initialize(left_expr, right_expr, op, post_fix = "")
873
- super(left_expr.expressions, :where)
874
- @left_expr = left_expr
875
- @right_expr = right_expr
876
- @op = op
877
- @post_fix = post_fix
878
- self.expressions.delete(left_expr)
879
- self.expressions.delete(right_expr)
880
- @left = quote(left_expr)
881
- if regexp?(right_expr)
882
- @op = "=~"
883
- @right = to_regexp(right_expr)
884
- else
885
- @right = right_expr && quote(right_expr)
886
- end
887
- @neg = nil
888
- end
889
-
890
- def separator
891
- " and "
892
- end
893
-
894
- def quote(val)
895
- if val.respond_to?(:var_name) && !val.kind_of?(Match)
896
- val.var_name
897
- else
898
- val.is_a?(String) ? %Q["#{val}"] : val
899
- end
900
- end
901
-
902
- def regexp?(right)
903
- @op == "=~" || right.is_a?(Regexp)
904
- end
905
-
906
- def to_regexp(val)
907
- %Q[/#{val.respond_to?(:source) ? val.source : val.to_s}/]
908
- end
909
-
910
- def count
911
- ExprOp.new(self, nil, 'count')
912
- end
913
-
914
- def &(other)
915
- ExprOp.new(self, other, "and")
916
- end
917
-
918
- def |(other)
919
- ExprOp.new(self, other, "or")
920
- end
921
-
922
- def -@
923
- @neg = "not"
924
- self
925
- end
926
-
927
- def not
928
- @neg = "not"
929
- self
930
- end
931
-
932
- # Only in 1.9
933
- if RUBY_VERSION > "1.9.0"
934
- eval %{
935
- def !
936
- @neg = "not"
937
- self
938
- end
939
- }
940
- end
941
-
942
- def left_to_s
943
- left.is_a?(ExprOp) ? "(#{left})" : left
944
- end
945
-
946
- def right_to_s
947
- right.is_a?(ExprOp) ? "(#{right})" : right
948
- end
949
-
950
- def binary!
951
- @binary = true
952
- self
953
- end
954
-
955
- def valid?
956
- # it is only valid in a where clause if it's either binary or it has right and left values
957
- @binary ? @left : @left && @right
958
- end
959
-
960
- def to_s
961
- if @right
962
- neg ? "#{neg}(#{left_to_s} #{op} #{right_to_s})" : "#{left_to_s} #{op} #{right_to_s}"
963
- else
964
- # binary operator
965
- neg ? "#{neg}#{op}(#{left_to_s}#{post_fix})" : "#{op}(#{left_to_s}#{post_fix})"
966
- end
967
- end
968
- end
969
-
970
- class Where < Expression
971
- def initialize(expressions, where_statement = nil)
972
- super(expressions, :where)
973
- @where_statement = where_statement
974
- end
975
-
976
- def to_s
977
- @where_statement.to_s
978
- end
979
- end
980
-
981
- class Predicate < Expression
982
- attr_accessor :params
983
-
984
- def initialize(expressions, params)
985
- @params = params
986
- @identifier = :x
987
- params[:input].referenced! if params[:input].respond_to?(:referenced!)
988
- super(expressions, params[:clause])
989
- end
990
-
991
- def identifier(i)
992
- @identifier = i
993
- self
994
- end
995
-
996
- def to_s
997
- input = params[:input]
998
- if input.kind_of?(Property)
999
- yield_param = Property.new([], @identifier, nil)
1000
- args = ""
1001
- else
1002
- yield_param = NodeVar.new([], []).as(@identifier.to_sym)
1003
- args = "(#{input.var_name})"
1004
- end
1005
- context = Neo4j::Cypher.new(yield_param, &params[:predicate_block])
1006
- context.expressions.each { |e| e.clause = nil }
1007
- if params[:clause] == :return
1008
- where_or_colon = ':'
1009
- else
1010
- where_or_colon = 'WHERE'
1011
- end
1012
- predicate_value = context.to_s[1..-1] # skip separator ,
1013
- "#{params[:op]}(#@identifier in #{params[:iterable]}#{args} #{where_or_colon} #{predicate_value})"
1014
- end
1015
- end
1016
-
1017
- class Entities
1018
- include PredicateMethods
1019
- attr_reader :input, :expressions, :iterable
1020
-
1021
- def initialize(expressions, iterable, input)
1022
- @iterable = iterable
1023
- @input = input
1024
- @expressions = expressions
1025
- end
1026
-
1027
- end
1028
-
1029
- end
1030
-
1031
- end
1032
-
1033
- end