neo4j-core 3.0.0.alpha.13 → 3.0.0.alpha.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -49
  3. data/lib/mydb/active_tx_log +1 -0
  4. data/lib/mydb/index/lucene-store.db +0 -0
  5. data/lib/mydb/index/lucene.log.1 +0 -0
  6. data/lib/mydb/index/lucene.log.active +0 -0
  7. data/lib/mydb/lock +0 -0
  8. data/lib/mydb/messages.log +313 -0
  9. data/lib/mydb/neostore +0 -0
  10. data/lib/mydb/neostore.id +0 -0
  11. data/lib/mydb/neostore.labeltokenstore.db +0 -0
  12. data/lib/mydb/neostore.labeltokenstore.db.id +0 -0
  13. data/lib/mydb/neostore.labeltokenstore.db.names +0 -0
  14. data/lib/mydb/neostore.labeltokenstore.db.names.id +0 -0
  15. data/lib/mydb/neostore.nodestore.db +0 -0
  16. data/lib/mydb/neostore.nodestore.db.id +0 -0
  17. data/lib/mydb/neostore.nodestore.db.labels +0 -0
  18. data/lib/mydb/neostore.nodestore.db.labels.id +0 -0
  19. data/lib/mydb/neostore.propertystore.db +0 -0
  20. data/lib/mydb/neostore.propertystore.db.arrays +0 -0
  21. data/lib/mydb/neostore.propertystore.db.arrays.id +0 -0
  22. data/lib/mydb/neostore.propertystore.db.id +0 -0
  23. data/lib/mydb/neostore.propertystore.db.index +0 -0
  24. data/lib/mydb/neostore.propertystore.db.index.id +0 -0
  25. data/lib/mydb/neostore.propertystore.db.index.keys +0 -0
  26. data/lib/mydb/neostore.propertystore.db.index.keys.id +0 -0
  27. data/lib/mydb/neostore.propertystore.db.strings +0 -0
  28. data/lib/mydb/neostore.propertystore.db.strings.id +0 -0
  29. data/lib/mydb/neostore.relationshipstore.db +0 -0
  30. data/lib/mydb/neostore.relationshipstore.db.id +0 -0
  31. data/lib/mydb/neostore.relationshiptypestore.db +0 -0
  32. data/lib/mydb/neostore.relationshiptypestore.db.id +0 -0
  33. data/lib/mydb/neostore.relationshiptypestore.db.names +0 -0
  34. data/lib/mydb/neostore.relationshiptypestore.db.names.id +0 -0
  35. data/lib/mydb/neostore.schemastore.db +0 -0
  36. data/lib/mydb/neostore.schemastore.db.id +0 -0
  37. data/lib/mydb/nioneo_logical.log.1 +0 -0
  38. data/lib/mydb/nioneo_logical.log.active +0 -0
  39. data/lib/mydb/schema/label/lucene/write.lock +0 -0
  40. data/lib/mydb/store_lock +0 -0
  41. data/lib/mydb/tm_tx_log.1 +0 -0
  42. data/lib/neo4j-core.rb +1 -2
  43. data/lib/neo4j-core/query_builder.rb +200 -0
  44. data/lib/neo4j-core/version.rb +1 -1
  45. data/lib/neo4j-embedded.rb +1 -0
  46. data/lib/neo4j-embedded/cypher_response.rb +89 -0
  47. data/lib/neo4j-embedded/cypher_response.rb~ +85 -0
  48. data/lib/neo4j-embedded/embedded_node.rb +12 -0
  49. data/lib/neo4j-embedded/embedded_node.rb~ +201 -0
  50. data/lib/neo4j-embedded/embedded_relationship.rb +8 -0
  51. data/lib/neo4j-embedded/embedded_relationship.rb~ +62 -0
  52. data/lib/neo4j-embedded/embedded_session.rb +20 -12
  53. data/lib/neo4j-embedded/embedded_session.rb~ +145 -0
  54. data/lib/neo4j-server/cypher_relationship.rb +6 -11
  55. data/lib/neo4j-server/cypher_response.rb +43 -5
  56. data/lib/neo4j-server/cypher_response.rb~ +155 -0
  57. data/lib/neo4j-server/cypher_session.rb +54 -19
  58. data/lib/neo4j/label.rb +7 -51
  59. data/lib/neo4j/node.rb +21 -19
  60. data/lib/neo4j/relationship.rb +7 -7
  61. data/lib/neo4j/session.rb +70 -28
  62. data/lib/neo4j/session.rb~ +202 -0
  63. data/neo4j-core.gemspec +0 -1
  64. metadata +49 -16
data/lib/mydb/neostore ADDED
Binary file
Binary file
File without changes
File without changes
Binary file
File without changes
File without changes
File without changes
File without changes
Binary file
Binary file
Binary file
Binary file
File without changes
File without changes
File without changes
data/lib/neo4j-core.rb CHANGED
@@ -1,12 +1,11 @@
1
1
  require 'forwardable'
2
2
  require 'fileutils'
3
3
 
4
- require 'neo4j-cypher'
5
-
6
4
  require 'neo4j/property_validator'
7
5
  require 'neo4j/property_container'
8
6
  require 'neo4j-core/helpers'
9
7
  require 'neo4j-core/cypher_translator'
8
+ require 'neo4j-core/query_builder'
10
9
 
11
10
  require 'neo4j/entity_equality'
12
11
  require 'neo4j/node'
@@ -0,0 +1,200 @@
1
+ module Neo4j::Core
2
+
3
+ class QueryBuilder
4
+ include CypherTranslator
5
+
6
+ DEFAULT_VAR_NAME = :n
7
+
8
+ class InvalidQueryError < StandardError;
9
+ end
10
+
11
+ def initialize(map_return={})
12
+ @map_return = map_return
13
+ @map_return[:node] = ->(id) { "ID(#{id})" }
14
+ end
15
+
16
+ # TODO should be moved somewhere else
17
+ def self.default_cypher_map_return_procs
18
+ {
19
+ id_to_node: ->(column) { Neo4j::Node.load(column) },
20
+ to_node: ->(column) { column.wrapper }, # for embedded db
21
+ value: ->(column) { column },
22
+ id_to_rel: ->(column) { Neo4j::Relationship.load(column) },
23
+ to_rel: ->(column) { column.wrapper } # for embedded db
24
+ }
25
+ end
26
+
27
+
28
+ def to_query_hash(params, default_map_return)
29
+ if params.first.is_a?(Hash)
30
+ hash = params.first.clone
31
+ hash[:map_return] ||= default_map_return unless hash[:q] || hash[:return]
32
+ hash[:map_return] ||= :value if hash[:return].is_a?(Symbol)
33
+ return hash
34
+ else
35
+ hash = (params[1] && params[1].clone) || {}
36
+ hash[:q] = params[0]
37
+ return hash
38
+ end
39
+ end
40
+
41
+ def to_map_return_procs(query_hash)
42
+ map_return_procs = query_hash[:map_return_procs] || self.class.default_cypher_map_return_procs
43
+ map_return = query_hash[:map_return]
44
+ case map_return
45
+ when NilClass
46
+ return {}
47
+ when Symbol, String
48
+ return map_return_procs[map_return.to_sym]
49
+ when Hash
50
+ map_return.keys.inject({}) do |ack, key|
51
+ proc_key = map_return[key]
52
+ ack[key] = map_return_procs[proc_key]
53
+ raise InvalidQueryError.new("Illegal map_return, '#{ack[key]}' not defined for #{key}") unless ack[key]
54
+ ack
55
+ end
56
+ end
57
+ end
58
+
59
+ def to_cypher(query_hash)
60
+ return query_hash[:q] if query_hash[:q]
61
+ match_parts = label_parts(query_hash[:label])
62
+ match_parts += match_parts(query_hash[:match])
63
+ conditions_parts = conditions_parts(query_hash[:conditions])
64
+ conditions_parts += where_parts(query_hash[:where])
65
+
66
+ return_parts = return_parts(query_hash)
67
+ return_parts += order_parts(query_hash[:order])
68
+ return_parts += skip_parts(query_hash[:skip])
69
+ return_parts += limit_parts(query_hash[:limit])
70
+
71
+ cypher = "MATCH #{match_parts.join(',')}"
72
+ cypher += " WHERE #{conditions_parts.join(' AND ')}" if !conditions_parts.empty?
73
+ cypher + " RETURN #{return_parts.join(' ')}"
74
+ end
75
+
76
+
77
+ def order_parts(order)
78
+ return [] unless order
79
+ cypher = "ORDER BY "
80
+
81
+ handleHash = Proc.new do |hash|
82
+ if (hash.is_a?(Hash))
83
+ k, v = hash.first
84
+ raise "only :asc or :desc allowed in order, got #{query.inspect}" unless [:asc, :desc].include?(v)
85
+ v.to_sym == :asc ? "#{DEFAULT_VAR_NAME}.`#{k}`" : "#{DEFAULT_VAR_NAME}.`#{k}` DESC"
86
+ else
87
+ "#{DEFAULT_VAR_NAME}.`#{hash}`" unless hash.is_a?(Hash)
88
+ end
89
+ end
90
+
91
+ case order
92
+ when Array
93
+ cypher += order.map(&handleHash).join(', ')
94
+ when Hash
95
+ cypher += handleHash.call(order)
96
+ else
97
+ cypher += "#{DEFAULT_VAR_NAME}.`#{order}`"
98
+ end
99
+
100
+ [cypher]
101
+ end
102
+
103
+ def return_parts(query_hash)
104
+ query_hash[:return] ? [cypher_return(query_hash[:return])] : [cypher_default_return(query_hash[:label], query_hash)]
105
+ end
106
+
107
+ def cypher_return(ret)
108
+ case ret
109
+ when Array
110
+ ret.map { |r| cypher_return_val(r) }.join(',')
111
+ when String, Symbol
112
+ cypher_return_val(ret)
113
+ end
114
+
115
+ end
116
+
117
+ def cypher_default_return(label, query_hash)
118
+ raise InvalidQueryError, "Can't have default return for two labels" if label.is_a?(Hash) && label.key.size > 1
119
+ if (query_hash[:map_return] == :id_to_node)
120
+ label.is_a?(Hash) ? "ID(#{label.key.first})" : "ID(#{DEFAULT_VAR_NAME})"
121
+ elsif (query_hash[:map_return] == :to_node)
122
+ label.is_a?(Hash) ? "#{label.key.first}" : "#{DEFAULT_VAR_NAME}"
123
+ else
124
+ raise InvalidQueryError.new("Don't know how to generate a cypher return #{query_hash.inspect}")
125
+ end
126
+
127
+ end
128
+
129
+
130
+ def where_parts(conditions)
131
+ return [] unless conditions
132
+ conditions.is_a?(Array) ? conditions : [conditions]
133
+ end
134
+
135
+ def limit_parts(limit)
136
+ return [] unless limit
137
+ raise InvalidQueryError.new ":limit value not a number" unless limit.is_a?(Integer)
138
+ return ["LIMIT #{limit}"]
139
+ end
140
+
141
+ def skip_parts(skip)
142
+ return [] unless skip
143
+ raise InvalidQueryError.new ":skip value not a number" unless skip.is_a?(Integer)
144
+ return ["SKIP #{skip}"]
145
+ end
146
+
147
+ def conditions_parts(conditions)
148
+
149
+ return [] unless conditions
150
+ neo_id = conditions.delete(:neo_id)
151
+ conditions["id(#{as})"] = neo_id if neo_id
152
+
153
+ conditions.map do |key, value|
154
+ operator, value_string = case value
155
+ when Regexp
156
+ pattern = (value.casefold? ? "(?i)" : "") + value.source
157
+ ['=~', escape_value(pattern.gsub(/\\/, '\\\\\\'))]
158
+ else
159
+ ['=', escape_value(value)]
160
+ end
161
+
162
+ k = key.to_s.dup
163
+ k = "#{DEFAULT_VAR_NAME}.#{k}" unless k.match(/[\(\.]/)
164
+ k + operator + value_string.to_s
165
+ end
166
+ end
167
+
168
+ def label_parts(label)
169
+ case label
170
+ when NilClass then
171
+ []
172
+ when Hash
173
+ label.map { |variable, label_name| "(#{variable}:`#{label_name}`)" }
174
+ else
175
+ ["(n:`#{label}`)"]
176
+ end
177
+ end
178
+
179
+
180
+ def match_parts(match)
181
+ case match
182
+ when Array then
183
+ return match
184
+ when String then
185
+ return [match]
186
+ when NilClass
187
+ return []
188
+ else
189
+ raise InvalidQueryError, "Invalid value for 'match' query key #{match.inspect}"
190
+ end
191
+ end
192
+
193
+ def cypher_return_val(val)
194
+ val.is_a?(Symbol) ? "#{DEFAULT_VAR_NAME}.`#{val}` AS `#{val}`" : val
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
@@ -1,5 +1,5 @@
1
1
  module Neo4j
2
2
  module Core
3
- VERSION = "3.0.0.alpha.13"
3
+ VERSION = "3.0.0.alpha.14"
4
4
  end
5
5
  end
@@ -8,6 +8,7 @@ require 'neo4j-embedded/embedded_label'
8
8
  require 'neo4j-embedded/embedded_node'
9
9
  require 'neo4j-embedded/embedded_relationship'
10
10
  require 'neo4j-embedded/embedded_label'
11
+ require 'neo4j-embedded/cypher_response'
11
12
 
12
13
  # TODO replace this with https://github.com/intridea/hashie gem
13
14
  require 'neo4j-core/hash_with_indifferent_access'
@@ -0,0 +1,89 @@
1
+ module Neo4j::Embedded
2
+
3
+ # Wraps the Cypher query result.
4
+ # Loads the node and relationships wrapper if possible and use symbol as column keys.
5
+ # This is typically used in the native neo4j bindings since result does is not a Ruby enumerable with symbols as keys.
6
+ # @note The result is a once forward read only Enumerable, work if you need to read the result twice - use #to_a
7
+ #
8
+ class ResultWrapper
9
+ class ResultsAlreadyConsumedException < Exception;
10
+ end
11
+
12
+ include Enumerable
13
+
14
+ # @return the original result from the Neo4j Cypher Engine, once forward read only !
15
+ attr_reader :source
16
+
17
+ def initialize(source, map_return_procs, query)
18
+ @source = source
19
+ @unread = true
20
+ @map_return_procs = map_return_procs
21
+ @query = query
22
+ end
23
+
24
+ def to_s
25
+ @query
26
+ end
27
+
28
+ def inspect
29
+ "Enumerable query: '#{@query}'"
30
+ end
31
+
32
+ # @return [Array<Symbol>] the columns in the query result
33
+ def columns
34
+ @source.columns.map { |x| x.to_sym }
35
+ end
36
+
37
+ # for the Enumerable contract
38
+ def each(&block)
39
+ raise ResultsAlreadyConsumedException unless @unread
40
+
41
+ if (block)
42
+ case @map_return_procs
43
+ when NilClass then
44
+ each_no_mapping &block
45
+ when Hash then
46
+ each_multi_column_mapping &block
47
+ else
48
+ each_single_column_mapping &block
49
+ end
50
+ else
51
+ Enumerator.new(self)
52
+ end
53
+ end
54
+
55
+
56
+ private
57
+
58
+ def each_no_mapping
59
+ @source.each do |row|
60
+ hash = {}
61
+ row.each do |key, value|
62
+ out[key.to_sym] = value
63
+ end
64
+ yield hash
65
+ end
66
+ end
67
+
68
+ def each_multi_column_mapping
69
+ @source.each do |row|
70
+ hash = {}
71
+ row.each do |key, value|
72
+ k = key.to_sym
73
+ proc = @map_return_procs[k]
74
+ hash[k] = proc ? proc.call(value) : value
75
+ end
76
+ yield hash
77
+ end
78
+ end
79
+
80
+ def each_single_column_mapping
81
+ @source.each do |row|
82
+ result = @map_return_procs.call(row.values.first)
83
+ yield result
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+
@@ -0,0 +1,85 @@
1
+ module Neo4j::Embedded
2
+
3
+ # Wraps the Cypher query result.
4
+ # Loads the node and relationships wrapper if possible and use symbol as column keys.
5
+ # This is typically used in the native neo4j bindings since result does is not a Ruby enumerable with symbols as keys.
6
+ # @note The result is a once forward read only Enumerable, work if you need to read the result twice - use #to_a
7
+ #
8
+ class ResultWrapper
9
+ class ResultsAlreadyConsumedException < Exception;
10
+ end
11
+
12
+ include Enumerable
13
+
14
+ # @return the original result from the Neo4j Cypher Engine, once forward read only !
15
+ attr_reader :source
16
+
17
+ def initialize(source, map_return_procs, query)
18
+ @source = source
19
+ @unread = true
20
+ @map_return_procs = map_return_procs
21
+ @query = query
22
+ end
23
+
24
+ def to_s
25
+ @query
26
+ end
27
+
28
+ # @return [Array<Symbol>] the columns in the query result
29
+ def columns
30
+ @source.columns.map { |x| x.to_sym }
31
+ end
32
+
33
+ # for the Enumerable contract
34
+ def each(&block)
35
+ raise ResultsAlreadyConsumedException unless @unread
36
+
37
+ if (block)
38
+ case @map_return_procs
39
+ when NilClass then
40
+ each_no_mapping &block
41
+ when Hash then
42
+ each_multi_column_mapping &block
43
+ else
44
+ each_single_column_mapping &block
45
+ end
46
+ else
47
+ Enumerator.new(self)
48
+ end
49
+ end
50
+
51
+
52
+ private
53
+
54
+ def each_no_mapping
55
+ @source.each do |row|
56
+ hash = {}
57
+ row.each do |key, value|
58
+ out[key.to_sym] = value
59
+ end
60
+ yield hash
61
+ end
62
+ end
63
+
64
+ def each_multi_column_mapping
65
+ @source.each do |row|
66
+ hash = {}
67
+ row.each do |key, value|
68
+ k = key.to_sym
69
+ proc = @map_return_procs[k]
70
+ hash[k] = proc ? proc.call(value) : value
71
+ end
72
+ yield hash
73
+ end
74
+ end
75
+
76
+ def each_single_column_mapping
77
+ @source.each do |row|
78
+ result = @map_return_procs.call(row.values.first)
79
+ yield result
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+