neo4j-core 8.1.4 → 9.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +71 -8
  3. data/lib/neo4j-core.rb +3 -49
  4. data/lib/neo4j/core.rb +4 -0
  5. data/lib/neo4j/core/config.rb +13 -0
  6. data/lib/neo4j/core/cypher_session/adaptors.rb +15 -15
  7. data/lib/neo4j/core/cypher_session/adaptors/bolt.rb +39 -48
  8. data/lib/neo4j/core/cypher_session/adaptors/bolt/chunk_writer_io.rb +0 -4
  9. data/lib/neo4j/core/cypher_session/adaptors/bolt/pack_stream.rb +7 -3
  10. data/lib/neo4j/core/cypher_session/adaptors/embedded.rb +1 -2
  11. data/lib/neo4j/core/cypher_session/adaptors/has_uri.rb +4 -0
  12. data/lib/neo4j/core/cypher_session/adaptors/http.rb +1 -3
  13. data/lib/neo4j/core/cypher_session/responses.rb +1 -1
  14. data/lib/neo4j/core/cypher_session/responses/bolt.rb +0 -17
  15. data/lib/neo4j/core/cypher_session/responses/embedded.rb +9 -7
  16. data/lib/neo4j/core/cypher_session/responses/http.rb +3 -4
  17. data/lib/neo4j/core/cypher_session/transactions.rb +2 -0
  18. data/lib/{neo4j-core → neo4j/core}/helpers.rb +1 -14
  19. data/lib/neo4j/core/logging.rb +44 -0
  20. data/lib/{neo4j-core → neo4j/core}/query.rb +7 -6
  21. data/lib/{neo4j-core → neo4j/core}/query_clauses.rb +9 -16
  22. data/lib/{neo4j-core → neo4j/core}/query_find_in_batches.rb +3 -5
  23. data/lib/{neo4j-core → neo4j/core}/version.rb +1 -1
  24. data/lib/neo4j/transaction.rb +6 -8
  25. data/neo4j-core.gemspec +13 -11
  26. metadata +46 -50
  27. data/lib/ext/kernel.rb +0 -9
  28. data/lib/neo4j-core/active_entity.rb +0 -11
  29. data/lib/neo4j-core/label.rb +0 -9
  30. data/lib/neo4j-embedded.rb +0 -16
  31. data/lib/neo4j-embedded/cypher_response.rb +0 -71
  32. data/lib/neo4j-embedded/embedded_database.rb +0 -26
  33. data/lib/neo4j-embedded/embedded_ha_session.rb +0 -30
  34. data/lib/neo4j-embedded/embedded_impermanent_session.rb +0 -17
  35. data/lib/neo4j-embedded/embedded_label.rb +0 -88
  36. data/lib/neo4j-embedded/embedded_node.rb +0 -206
  37. data/lib/neo4j-embedded/embedded_relationship.rb +0 -77
  38. data/lib/neo4j-embedded/embedded_session.rb +0 -203
  39. data/lib/neo4j-embedded/embedded_transaction.rb +0 -30
  40. data/lib/neo4j-embedded/label.rb +0 -66
  41. data/lib/neo4j-embedded/property.rb +0 -106
  42. data/lib/neo4j-embedded/to_java.rb +0 -44
  43. data/lib/neo4j-server.rb +0 -12
  44. data/lib/neo4j-server/cypher_label.rb +0 -35
  45. data/lib/neo4j-server/cypher_node.rb +0 -221
  46. data/lib/neo4j-server/cypher_relationship.rb +0 -142
  47. data/lib/neo4j-server/cypher_response.rb +0 -248
  48. data/lib/neo4j-server/cypher_session.rb +0 -263
  49. data/lib/neo4j-server/cypher_transaction.rb +0 -100
  50. data/lib/neo4j-server/label.rb +0 -40
  51. data/lib/neo4j-server/resource.rb +0 -57
  52. data/lib/neo4j/entity_equality.rb +0 -8
  53. data/lib/neo4j/entity_marshal.rb +0 -20
  54. data/lib/neo4j/label.rb +0 -90
  55. data/lib/neo4j/node.rb +0 -216
  56. data/lib/neo4j/property_container.rb +0 -17
  57. data/lib/neo4j/property_validator.rb +0 -22
  58. data/lib/neo4j/relationship.rb +0 -161
  59. data/lib/neo4j/session.rb +0 -222
@@ -1,142 +0,0 @@
1
- module Neo4j
2
- module Server
3
- class CypherRelationship < Neo4j::Relationship
4
- include Neo4j::Server::Resource
5
- include Neo4j::Core::ActiveEntity
6
-
7
- MARSHAL_INSTANCE_VARIABLES = %i[@rel_type @props @start_node_neo_id @end_node_neo_id @id]
8
-
9
- def initialize(session, value)
10
- @session = session
11
- @response_hash = value
12
- @rel_type = @response_hash[:type]
13
- @props = @response_hash[:data]
14
- @start_node_neo_id = neo_id_integer(@response_hash[:start])
15
- @end_node_neo_id = neo_id_integer(@response_hash[:end])
16
- @id = @response_hash[:id]
17
- end
18
-
19
- def ==(other)
20
- other.class == self.class && other.neo_id == neo_id
21
- end
22
- alias eql? ==
23
-
24
- attr_reader :id
25
-
26
- def neo_id
27
- id
28
- end
29
-
30
- def inspect
31
- "CypherRelationship #{neo_id}"
32
- end
33
-
34
- def load_resource
35
- return if resource_data_present?
36
-
37
- @resource_data = @session._query_or_fail("#{match_start} RETURN n", true, neo_id: neo_id) # r.first_data
38
- end
39
-
40
- attr_reader :start_node_neo_id
41
-
42
- attr_reader :end_node_neo_id
43
-
44
- def _start_node_id
45
- @start_node_neo_id ||= get_node_id(:start)
46
- end
47
-
48
- def _end_node_id
49
- @end_node_neo_id ||= get_node_id(:end)
50
- end
51
-
52
- def _start_node
53
- @_start_node ||= Neo4j::Node._load(start_node_neo_id)
54
- end
55
-
56
- def _end_node
57
- load_resource
58
- @_end_node ||= Neo4j::Node._load(end_node_neo_id)
59
- end
60
-
61
- def get_node_id(direction)
62
- load_resource
63
- resource_url_id(resource_url(direction))
64
- end
65
-
66
- def get_property(key)
67
- @session._query_or_fail("#{match_start} RETURN n.`#{key}`", true, neo_id: neo_id)
68
- end
69
-
70
- def set_property(key, value)
71
- @session._query_or_fail("#{match_start} SET n.`#{key}` = {value}", false, value: value, neo_id: neo_id)
72
- end
73
-
74
- def remove_property(key)
75
- @session._query_or_fail("#{match_start} REMOVE n.`#{key}`", false, neo_id: neo_id)
76
- end
77
-
78
- # (see Neo4j::Relationship#props)
79
- def props
80
- if @props
81
- @props
82
- else
83
- hash = @session._query_entity_data("#{match_start} RETURN n", nil, neo_id: neo_id)
84
- @props = Hash[hash[:data].map { |k, v| [k, v] }]
85
- end
86
- end
87
-
88
- # (see Neo4j::Relationship#props=)
89
- def props=(properties)
90
- @session._query_or_fail("#{match_start} SET n = { props }", false, props: properties, neo_id: neo_id)
91
- properties
92
- end
93
-
94
- # (see Neo4j::Relationship#update_props)
95
- def update_props(properties)
96
- return if properties.empty?
97
-
98
- params = {}
99
- q = "#{match_start} SET " + properties.keys.each_with_index.map do |k, _i|
100
- param = k.to_s.tr_s('^a-zA-Z0-9', '_').gsub(/^_+|_+$/, '')
101
- params[param] = properties[k]
102
-
103
- "n.`#{k}`= {#{param}}"
104
- end.join(',')
105
-
106
- @session._query_or_fail(q, false, params.merge(neo_id: neo_id))
107
-
108
- properties
109
- end
110
-
111
- def rel_type
112
- @rel_type.to_sym
113
- end
114
-
115
- def del
116
- @session._query("#{match_start} DELETE n", neo_id: neo_id)
117
- end
118
- alias delete del
119
- alias destroy del
120
-
121
- def exist?
122
- response = @session._query("#{match_start} RETURN n", neo_id: neo_id)
123
- # binding.pry
124
- (response.data.nil? || response.data.empty?) ? false : true
125
- end
126
-
127
- private
128
-
129
- def match_start(identifier = 'n')
130
- "MATCH (node)-[#{identifier}]-() WHERE ID(#{identifier}) = {neo_id}"
131
- end
132
-
133
- def resource_data_present?
134
- !resource_data.nil? && !resource_data.empty?
135
- end
136
-
137
- def neo_id_integer(id_or_url)
138
- id_or_url.is_a?(Integer) ? id_or_url : id_or_url.split('/').last.to_i
139
- end
140
- end
141
- end
142
- end
@@ -1,248 +0,0 @@
1
- module Neo4j
2
- module Server
3
- class CypherResponse
4
- attr_reader :data, :columns, :error_msg, :error_status, :error_code, :response
5
-
6
- class ResponseError < StandardError
7
- attr_reader :status, :code
8
-
9
- def initialize(msg, status, code)
10
- super(msg)
11
- @status = status
12
- @code = code
13
- end
14
- end
15
-
16
- class ConstraintViolationError < ResponseError; end
17
-
18
- class HashEnumeration
19
- include Enumerable
20
- extend Forwardable
21
- def_delegator :@response, :error_msg
22
- def_delegator :@response, :error_status
23
- def_delegator :@response, :error_code
24
- def_delegator :@response, :columns
25
- def_delegator :@response, :struct
26
-
27
- def initialize(response, query)
28
- @response = response
29
- @query = query
30
- end
31
-
32
- def to_s
33
- @query
34
- end
35
-
36
- def inspect
37
- "Enumerable query: '#{@query}'"
38
- end
39
-
40
- def each
41
- @response.each_data_row { |row| yield struct_rows(row) }
42
- end
43
-
44
- def struct_rows(row)
45
- struct.new.tap do |result|
46
- row.each_with_index { |value, i| result[columns[i]] = value }
47
- end
48
- end
49
- end
50
-
51
- EMPTY_STRING = ''
52
- def to_struct_enumeration(cypher = EMPTY_STRING)
53
- HashEnumeration.new(self, cypher)
54
- end
55
-
56
- def to_node_enumeration(cypher = EMPTY_STRING, session = Neo4j::Session.current)
57
- Enumerator.new do |yielder|
58
- to_struct_enumeration(cypher).each do |row|
59
- yielder << row_pair_in_struct(row, session)
60
- end
61
- end
62
- end
63
-
64
- def row_pair_in_struct(row, session)
65
- @struct.new.tap do |result|
66
- row.each_pair do |column, value|
67
- result[column] = map_row_value(value, session)
68
- end
69
- end
70
- end
71
-
72
- def map_row_value(value, session)
73
- if value.is_a?(Hash) && looks_like_an_object?(value)
74
- hash_value_as_object(value, session)
75
- elsif value.is_a?(Array)
76
- value.map! { |v| map_row_value(v, session) }
77
- else
78
- value
79
- end
80
- end
81
-
82
- def hash_value_as_object(value, session)
83
- return value unless %i[node relationship].include?(identify_entity(value))
84
- add_entity_id(value)
85
-
86
- basic_obj = (node?(value) ? CypherNode : CypherRelationship).new(session, value)
87
- unwrapped? ? basic_obj : basic_obj.wrapper
88
- end
89
-
90
- def identify_entity(data)
91
- self_string = data[:self]
92
- if self_string
93
- if self_string.include?('node')
94
- :node
95
- elsif self_string.include?('relationship')
96
- :relationship
97
- end
98
- elsif %i[nodes relationships start end length].all? { |k| data.key?(k) }
99
- :path
100
- end
101
- end
102
-
103
- def looks_like_an_object?(value)
104
- value[:labels] || value[:type]
105
- end
106
-
107
- def unwrapped!
108
- @_unwrapped_obj = true
109
- end
110
-
111
- def unwrapped?
112
- !!@_unwrapped_obj
113
- end
114
-
115
- def node?(value)
116
- value[:labels]
117
- end
118
-
119
- attr_reader :struct
120
-
121
- def initialize(response, uncommited = false)
122
- @response = response
123
- @uncommited = uncommited
124
- end
125
-
126
- def entity_data(id = nil)
127
- if @uncommited
128
- data = @data.first[:row].first
129
- data.is_a?(Hash) ? {data: data, id: id} : data
130
- else
131
- data = @data[0][0]
132
- data.is_a?(Hash) ? add_entity_id(data) : data
133
- end
134
- end
135
-
136
- def first_data
137
- if @uncommited
138
- @data.first[:row].first
139
- else
140
- data = @data[0][0]
141
- data.is_a?(Hash) ? add_entity_id(data) : data
142
- end
143
- end
144
-
145
- def add_entity_id(data)
146
- data[:id] = if data[:metadata] && data[:metadata][:id]
147
- data[:metadata][:id]
148
- else
149
- data[:self].split('/')[-1].to_i
150
- end
151
- data
152
- end
153
-
154
- def error?
155
- !!@error
156
- end
157
-
158
- def raise_if_cypher_error!
159
- raise_cypher_error if error?
160
- end
161
-
162
- RETRYABLE_ERROR_STATUSES = %w[DeadlockDetectedException AcquireLockTimeoutException ExternalResourceFailureException UnknownFailureException]
163
- def retryable_error?
164
- return unless error?
165
- RETRYABLE_ERROR_STATUSES.include?(@error_status)
166
- end
167
-
168
- def data?
169
- !response.body[:data].nil?
170
- end
171
-
172
- def raise_unless_response_code(code)
173
- fail "Response code #{response.status}, expected #{code} for #{response.headers[:location]}, #{response.body}" unless response.status == code
174
- end
175
-
176
- def each_data_row
177
- data.each do |r|
178
- yieldable = if @uncommitted
179
- r[:row]
180
- else
181
- transaction_row?(r) ? r[:rest] : r
182
- end
183
- yield yieldable
184
- end
185
- end
186
-
187
- def transaction_response?
188
- response.respond_to?(:body) && !response.body[:commit].nil?
189
- end
190
-
191
- def set_data(response)
192
- @data = response[:data]
193
- @columns = response[:columns]
194
- @struct = @columns.empty? ? Object.new : Struct.new(*@columns.map(&:to_sym))
195
- self
196
- end
197
-
198
- def set_error(error)
199
- @error = true
200
- @error_msg = error[:message]
201
- @error_status = error[:status] || error[:exception] || error[:code]
202
- @error_code = error[:code] || error[:fullname]
203
- self
204
- end
205
-
206
- CONSTRAINT_ERROR = 'Neo.ClientError.Schema.ConstraintViolation'
207
- def raise_error
208
- fail 'Tried to raise error without an error' unless @error
209
- error_class = constraint_error? ? ConstraintViolationError : ResponseError
210
- fail error_class.new(@error_msg, @error_status, @error_code)
211
- end
212
-
213
- def constraint_error?
214
- @error_code == CONSTRAINT_ERROR || (@error_msg || '').include?('already exists with')
215
- end
216
-
217
- def raise_cypher_error
218
- fail 'Tried to raise error without an error' unless @error
219
- fail Neo4j::Session::CypherError.new(@error_msg, @error_code, @error_status)
220
- end
221
-
222
-
223
- def self.create_with_no_tx(response)
224
- case response.status
225
- when 200 then new(response).set_data(response.body)
226
- when 400 then new(response).set_error(response.body)
227
- else
228
- fail "Unknown response code #{response.status} for #{response.env[:url]}"
229
- end
230
- end
231
-
232
- def self.create_with_tx(response)
233
- fail "Unknown response code #{response.status} for #{response.request_uri}" unless response.status == 200
234
-
235
- new(response, true).tap do |cr|
236
- body = response.body
237
- body[:errors].empty? ? cr.set_data(body[:results].first) : cr.set_error(body[:errors].first)
238
- end
239
- end
240
-
241
- private
242
-
243
- def transaction_row?(row)
244
- row.is_a?(Hash) && row[:rest] && row[:row]
245
- end
246
- end
247
- end
248
- end
@@ -1,263 +0,0 @@
1
- require 'uri'
2
-
3
- module Neo4j
4
- module Server
5
- Neo4j::Session.register_db(:server_db) do |endpoint_url, url_opts|
6
- Neo4j::Server::CypherSession.open(endpoint_url, url_opts)
7
- end
8
-
9
- class CypherSession < Neo4j::Session
10
- include Resource
11
-
12
- alias super_query query
13
- attr_reader :connection
14
-
15
- def initialize(data_url, connection)
16
- @connection = connection
17
- Neo4j::Session.register(self)
18
- initialize_resource(data_url)
19
- Neo4j::Session._notify_listeners(:session_available, self)
20
- end
21
-
22
- # @param [Hash] params could be empty or contain basic authentication user and password
23
- # @return [Faraday]
24
- # @see https://github.com/lostisland/faraday
25
- def self.create_connection(params, url = nil)
26
- init_params = params[:initialize] && params.delete(:initialize)
27
- conn = Faraday.new(url, init_params) do |b|
28
- b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth]
29
- b.request :multi_json
30
- # b.response :logger, ::Logger.new(STDOUT), bodies: true
31
-
32
- b.response :multi_json, symbolize_keys: true, content_type: 'application/json'
33
- # b.use Faraday::Response::RaiseError
34
- require 'typhoeus'
35
- require 'typhoeus/adapters/faraday'
36
- b.adapter :typhoeus
37
- # b.adapter Faraday.default_adapter
38
- end
39
- conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string}
40
- conn
41
- end
42
-
43
- # Opens a session to the database
44
- # @see Neo4j::Session#open
45
- #
46
- # @param [String] endpoint_url - the url to the neo4j server, defaults to 'http://localhost:7474'
47
- # @param [Hash] params faraday params, see #create_connection or an already created faraday connection
48
- def self.open(endpoint_url = nil, params = {})
49
- extract_basic_auth(endpoint_url, params)
50
- url = endpoint_url || 'http://localhost:7474'
51
- connection = params[:connection] || create_connection(params, url)
52
- response = connection.get(url)
53
- fail "Server not available on #{url} (response code #{response.status})" unless response.status == 200
54
- establish_session(response.body, connection)
55
- end
56
-
57
- def self.establish_session(root_data, connection)
58
- data_url = root_data[:data]
59
- data_url << '/' unless data_url.nil? || data_url.end_with?('/')
60
- CypherSession.new(data_url, connection)
61
- end
62
-
63
- def self.extract_basic_auth(url, params)
64
- return unless url && URI(url).userinfo
65
- params[:basic_auth] = {username: URI(url).user, password: URI(url).password}
66
- end
67
-
68
- private_class_method :extract_basic_auth
69
-
70
- def db_type
71
- :server_db
72
- end
73
-
74
- def to_s
75
- "#{self.class} url: '#{@resource_url}'"
76
- end
77
-
78
- def inspect
79
- "#{self} version: '#{version}'"
80
- end
81
-
82
- def version
83
- resource_data ? resource_data[:neo4j_version] : ''
84
- end
85
-
86
- def initialize_resource(data_url)
87
- response = @connection.get(data_url)
88
- expect_response_code!(response, 200)
89
- data_resource = response.body
90
- fail "No data_resource for #{response.body}" unless data_resource
91
- # store the resource data
92
- init_resource_data(data_resource, data_url)
93
- end
94
-
95
- def self.transaction_class
96
- Neo4j::Server::CypherTransaction
97
- end
98
-
99
- # Duplicate of CypherSession::Adaptor::Base#transaction
100
- def transaction
101
- return self.class.transaction_class.new(self) if !block_given?
102
-
103
- begin
104
- tx = transaction
105
-
106
- yield tx
107
- rescue Exception => e # rubocop:disable Lint/RescueException
108
- tx.mark_failed
109
-
110
- raise e
111
- ensure
112
- tx.close
113
- end
114
- end
115
-
116
- def create_node(props = nil, labels = [])
117
- label_string = labels.empty? ? '' : (':' + labels.map { |k| "`#{k}`" }.join(':'))
118
- if !props.nil?
119
- prop = '{props}'
120
- props.each_key { |k| props.delete(k) if props[k].nil? }
121
- end
122
-
123
- id = _query_or_fail("CREATE (n#{label_string} #{prop}) RETURN ID(n)", true, props: props)
124
- CypherNode.new(self, props.nil? ? id : {id: id, metadata: {labels: labels}, data: props})
125
- end
126
-
127
- def load_node(neo_id)
128
- query.unwrapped.match(:n).where(n: {neo_id: neo_id}).pluck(:n).first
129
- end
130
-
131
- def load_relationship(neo_id)
132
- query.unwrapped.optional_match('(n)-[r]-()').where(r: {neo_id: neo_id}).pluck(:r).first
133
- rescue Neo4j::Session::CypherError => cypher_error
134
- return nil if cypher_error.message =~ /not found$/
135
-
136
- raise cypher_error
137
- end
138
-
139
- def create_label(name)
140
- CypherLabel.new(self, name)
141
- end
142
-
143
- def uniqueness_constraints(label)
144
- schema_properties("/db/data/schema/constraint/#{label}/uniqueness")
145
- end
146
-
147
- def indexes(label)
148
- schema_properties("/db/data/schema/index/#{label}")
149
- end
150
-
151
- def schema_properties(query_string)
152
- response = @connection.get(query_string)
153
- expect_response_code!(response, 200)
154
- {property_keys: response.body.map! { |row| row[:property_keys].map(&:to_sym) }}
155
- end
156
-
157
- def find_all_nodes(label_name)
158
- search_result_to_enumerable_first_column(_query_or_fail("MATCH (n:`#{label_name}`) RETURN ID(n)"))
159
- end
160
-
161
- def find_nodes(label_name, key, value)
162
- value = "'#{value}'" if value.is_a? String
163
-
164
- response = _query_or_fail("MATCH (n:`#{label_name}`) WHERE n.#{key} = #{value} RETURN ID(n)")
165
- search_result_to_enumerable_first_column(response)
166
- end
167
-
168
- def query(*args)
169
- if [[String], [String, Hash]].include?(args.map(&:class))
170
- response = _query(*args)
171
- response.raise_error if response.error?
172
- response.to_node_enumeration(args[0])
173
- else
174
- options = args[0] || {}
175
- Neo4j::Core::Query.new(options.merge(session: self))
176
- end
177
- end
178
-
179
- def _query_data(query)
180
- r = _query_or_fail(query, true)
181
- Neo4j::Transaction.current ? r : r[:data]
182
- end
183
-
184
- DEFAULT_RETRY_COUNT = ENV['NEO4J_RETRY_COUNT'].nil? ? 10 : ENV['NEO4J_RETRY_COUNT'].to_i
185
-
186
- def _query_or_fail(query, single_row = false, params = {}, retry_count = DEFAULT_RETRY_COUNT)
187
- query, params = query_and_params(query, params)
188
-
189
- response = _query(query, params)
190
- if response.error?
191
- _retry_or_raise(query, params, single_row, retry_count, response)
192
- else
193
- single_row ? response.first_data : response
194
- end
195
- end
196
-
197
- def query_and_params(query_or_query_string, params)
198
- if query_or_query_string.is_a?(::Neo4j::Core::Query)
199
- cypher = query_or_query_string.to_cypher
200
- [cypher, query_or_query_string.send(:merge_params).merge(params)]
201
- else
202
- [query_or_query_string, params]
203
- end
204
- end
205
-
206
- def _retry_or_raise(query, params, single_row, retry_count, response)
207
- response.raise_error unless response.retryable_error?
208
- retry_count > 0 ? _query_or_fail(query, single_row, params, retry_count - 1) : response.raise_error
209
- end
210
-
211
- def _query_entity_data(query, id = nil, params = {})
212
- _query(query, params).tap(&:raise_if_cypher_error!).entity_data(id)
213
- end
214
-
215
- def _query(query, params = {}, options = {})
216
- query, params = query_and_params(query, params)
217
-
218
- ActiveSupport::Notifications.instrument('neo4j.cypher_query', params: params, context: options[:context],
219
- cypher: query, pretty_cypher: options[:pretty_cypher]) do
220
- if current_transaction
221
- current_transaction._query(query, params)
222
- else
223
- query = params.nil? ? {'query' => query} : {'query' => query, 'params' => params}
224
- response = @connection.post(resource_url(:cypher), query)
225
- CypherResponse.create_with_no_tx(response)
226
- end
227
- end
228
- end
229
-
230
- def search_result_to_enumerable_first_column(response)
231
- return [] unless response.data
232
-
233
- Enumerator.new do |yielder|
234
- response.data.each do |data|
235
- if current_transaction
236
- data[:row].each do |id|
237
- yielder << CypherNode.new(self, id).wrapper
238
- end
239
- else
240
- yielder << CypherNode.new(self, data[0]).wrapper
241
- end
242
- end
243
- end
244
- end
245
-
246
- def current_transaction
247
- Neo4j::Transaction.current_for(self)
248
- end
249
-
250
- EMPTY = ''
251
- NEWLINE_W_SPACES = "\n "
252
- def self.log_with
253
- ActiveSupport::Notifications.subscribe('neo4j.cypher_query') do |_, start, finish, _id, payload|
254
- ms = (finish - start) * 1000
255
- params_string = (payload[:params] && !payload[:params].empty? ? "| #{payload[:params].inspect}" : EMPTY)
256
- cypher = payload[:pretty_cypher] ? NEWLINE_W_SPACES + payload[:pretty_cypher].gsub(/\n/, NEWLINE_W_SPACES) : payload[:cypher]
257
-
258
- yield(" #{ANSI::CYAN}#{payload[:context] || 'CYPHER'}#{ANSI::CLEAR} #{ANSI::YELLOW}#{ms.round}ms#{ANSI::CLEAR} #{cypher} #{params_string}")
259
- end
260
- end
261
- end
262
- end
263
- end