neo4j-core 6.1.6 → 7.0.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -9
- data/README.md +48 -0
- data/lib/neo4j-core.rb +23 -0
- data/lib/neo4j-core/helpers.rb +8 -0
- data/lib/neo4j-core/query.rb +23 -20
- data/lib/neo4j-core/query_clauses.rb +18 -32
- data/lib/neo4j-core/query_find_in_batches.rb +3 -1
- data/lib/neo4j-core/version.rb +1 -1
- data/lib/neo4j-embedded/cypher_response.rb +4 -0
- data/lib/neo4j-embedded/embedded_database.rb +3 -5
- data/lib/neo4j-embedded/embedded_node.rb +4 -4
- data/lib/neo4j-embedded/embedded_session.rb +21 -10
- data/lib/neo4j-embedded/embedded_transaction.rb +4 -10
- data/lib/neo4j-server/cypher_node.rb +5 -4
- data/lib/neo4j-server/cypher_relationship.rb +3 -3
- data/lib/neo4j-server/cypher_response.rb +4 -0
- data/lib/neo4j-server/cypher_session.rb +31 -22
- data/lib/neo4j-server/cypher_transaction.rb +23 -15
- data/lib/neo4j-server/resource.rb +3 -4
- data/lib/neo4j/core/cypher_session.rb +17 -9
- data/lib/neo4j/core/cypher_session/adaptors.rb +116 -33
- data/lib/neo4j/core/cypher_session/adaptors/bolt.rb +331 -0
- data/lib/neo4j/core/cypher_session/adaptors/bolt/chunk_writer_io.rb +76 -0
- data/lib/neo4j/core/cypher_session/adaptors/bolt/pack_stream.rb +288 -0
- data/lib/neo4j/core/cypher_session/adaptors/embedded.rb +60 -29
- data/lib/neo4j/core/cypher_session/adaptors/has_uri.rb +63 -0
- data/lib/neo4j/core/cypher_session/adaptors/http.rb +123 -119
- data/lib/neo4j/core/cypher_session/responses.rb +17 -2
- data/lib/neo4j/core/cypher_session/responses/bolt.rb +135 -0
- data/lib/neo4j/core/cypher_session/responses/embedded.rb +46 -11
- data/lib/neo4j/core/cypher_session/responses/http.rb +49 -40
- data/lib/neo4j/core/cypher_session/transactions.rb +33 -0
- data/lib/neo4j/core/cypher_session/transactions/bolt.rb +36 -0
- data/lib/neo4j/core/cypher_session/transactions/embedded.rb +32 -0
- data/lib/neo4j/core/cypher_session/transactions/http.rb +52 -0
- data/lib/neo4j/core/instrumentable.rb +2 -2
- data/lib/neo4j/core/label.rb +182 -0
- data/lib/neo4j/core/node.rb +8 -3
- data/lib/neo4j/core/relationship.rb +12 -4
- data/lib/neo4j/entity_equality.rb +1 -1
- data/lib/neo4j/session.rb +4 -5
- data/lib/neo4j/transaction.rb +108 -72
- data/neo4j-core.gemspec +6 -6
- metadata +34 -40
@@ -1,12 +1,11 @@
|
|
1
1
|
module Neo4j
|
2
2
|
module Embedded
|
3
|
-
class EmbeddedTransaction
|
3
|
+
class EmbeddedTransaction < Neo4j::Transaction::Base
|
4
4
|
attr_reader :root_tx
|
5
|
-
include Neo4j::Transaction::Instance
|
6
5
|
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
6
|
+
def initialize(session)
|
7
|
+
super
|
8
|
+
@root_tx = @session.begin_tx
|
10
9
|
end
|
11
10
|
|
12
11
|
def acquire_read_lock(entity)
|
@@ -17,11 +16,6 @@ module Neo4j
|
|
17
16
|
@root_tx.acquire_write_lock(entity)
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
"EmbeddedTransaction [nested: #{@pushed_nested} failed?: #{failure?} active: #{Neo4j::Transaction.current == self}]"
|
23
|
-
end
|
24
|
-
|
25
19
|
def delete
|
26
20
|
@root_tx.failure
|
27
21
|
@root_tx.close
|
@@ -32,7 +32,7 @@ module Neo4j
|
|
32
32
|
# (see Neo4j::Node#create_rel)
|
33
33
|
def create_rel(type, other_node, props = nil)
|
34
34
|
q = @session.query.match(:a, :b).where(a: {neo_id: neo_id}, b: {neo_id: other_node.neo_id})
|
35
|
-
|
35
|
+
.create("(a)-[r:`#{type}`]->(b)").break.set(r: props).return(r: :neo_id)
|
36
36
|
|
37
37
|
id = @session._query_or_fail(q, true)
|
38
38
|
|
@@ -138,8 +138,8 @@ module Neo4j
|
|
138
138
|
@session._query_or_fail(query, false)
|
139
139
|
end
|
140
140
|
|
141
|
-
|
142
|
-
|
141
|
+
alias delete del
|
142
|
+
alias destroy del
|
143
143
|
|
144
144
|
# (see Neo4j::Node#exist?)
|
145
145
|
def exist?
|
@@ -193,10 +193,11 @@ module Neo4j
|
|
193
193
|
|
194
194
|
private
|
195
195
|
|
196
|
+
DEFAULT_RELATIONSHIP_ARROW_DIRECTION = :both
|
196
197
|
def relationship_arrow(match)
|
197
198
|
rel_spec = match[:type] ? "[r:`#{match[:type]}`]" : '[r]'
|
198
199
|
|
199
|
-
case match[:dir] ||
|
200
|
+
case match[:dir] || DEFAULT_RELATIONSHIP_ARROW_DIRECTION
|
200
201
|
when :outgoing then "-#{rel_spec}->"
|
201
202
|
when :incoming then "<-#{rel_spec}-"
|
202
203
|
when :both then "-#{rel_spec}-"
|
@@ -19,7 +19,7 @@ module Neo4j
|
|
19
19
|
def ==(other)
|
20
20
|
other.class == self.class && other.neo_id == neo_id
|
21
21
|
end
|
22
|
-
|
22
|
+
alias eql? ==
|
23
23
|
|
24
24
|
attr_reader :id
|
25
25
|
|
@@ -115,8 +115,8 @@ module Neo4j
|
|
115
115
|
def del
|
116
116
|
@session._query("#{match_start} DELETE n", neo_id: neo_id)
|
117
117
|
end
|
118
|
-
|
119
|
-
|
118
|
+
alias delete del
|
119
|
+
alias destroy del
|
120
120
|
|
121
121
|
def exist?
|
122
122
|
response = @session._query("#{match_start} RETURN n", neo_id: neo_id)
|
@@ -155,6 +155,10 @@ module Neo4j
|
|
155
155
|
!!@error
|
156
156
|
end
|
157
157
|
|
158
|
+
def raise_if_cypher_error!
|
159
|
+
raise_cypher_error if error?
|
160
|
+
end
|
161
|
+
|
158
162
|
RETRYABLE_ERROR_STATUSES = %w(DeadlockDetectedException AcquireLockTimeoutException ExternalResourceFailureException UnknownFailureException)
|
159
163
|
def retryable_error?
|
160
164
|
return unless error?
|
@@ -9,7 +9,7 @@ module Neo4j
|
|
9
9
|
class CypherSession < Neo4j::Session
|
10
10
|
include Resource
|
11
11
|
|
12
|
-
|
12
|
+
alias super_query query
|
13
13
|
attr_reader :connection
|
14
14
|
|
15
15
|
def initialize(data_url, connection)
|
@@ -27,7 +27,7 @@ module Neo4j
|
|
27
27
|
conn = Faraday.new(url, init_params) do |b|
|
28
28
|
b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth]
|
29
29
|
b.request :multi_json
|
30
|
-
# b.response :logger
|
30
|
+
# b.response :logger, ::Logger.new(STDOUT), bodies: true
|
31
31
|
|
32
32
|
b.response :multi_json, symbolize_keys: true, content_type: 'application/json'
|
33
33
|
# b.use Faraday::Response::RaiseError
|
@@ -90,14 +90,25 @@ module Neo4j
|
|
90
90
|
init_resource_data(data_resource, data_url)
|
91
91
|
end
|
92
92
|
|
93
|
-
def
|
94
|
-
|
95
|
-
Neo4j::Transaction.unregister_current
|
93
|
+
def self.transaction_class
|
94
|
+
Neo4j::Server::CypherTransaction
|
96
95
|
end
|
97
96
|
|
98
|
-
|
99
|
-
|
100
|
-
|
97
|
+
# Duplicate of CypherSession::Adaptor::Base#transaction
|
98
|
+
def transaction
|
99
|
+
return self.class.transaction_class.new(self) if !block_given?
|
100
|
+
|
101
|
+
begin
|
102
|
+
tx = transaction
|
103
|
+
|
104
|
+
yield tx
|
105
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
106
|
+
tx.mark_failed
|
107
|
+
|
108
|
+
raise e
|
109
|
+
ensure
|
110
|
+
tx.close
|
111
|
+
end
|
101
112
|
end
|
102
113
|
|
103
114
|
def create_node(props = nil, labels = [])
|
@@ -118,7 +129,7 @@ module Neo4j
|
|
118
129
|
def load_relationship(neo_id)
|
119
130
|
query.unwrapped.optional_match('(n)-[r]-()').where(r: {neo_id: neo_id}).pluck(:r).first
|
120
131
|
rescue Neo4j::Session::CypherError => cypher_error
|
121
|
-
return nil if cypher_error.message
|
132
|
+
return nil if cypher_error.message =~ /not found$/
|
122
133
|
|
123
134
|
raise cypher_error
|
124
135
|
end
|
@@ -154,12 +165,9 @@ module Neo4j
|
|
154
165
|
|
155
166
|
def query(*args)
|
156
167
|
if [[String], [String, Hash]].include?(args.map(&:class))
|
157
|
-
|
158
|
-
params = args[1]
|
159
|
-
|
160
|
-
response = _query(query, params)
|
168
|
+
response = _query(*args)
|
161
169
|
response.raise_error if response.error?
|
162
|
-
response.to_node_enumeration(
|
170
|
+
response.to_node_enumeration(args[0])
|
163
171
|
else
|
164
172
|
options = args[0] || {}
|
165
173
|
Neo4j::Core::Query.new(options.merge(session: self))
|
@@ -199,19 +207,16 @@ module Neo4j
|
|
199
207
|
end
|
200
208
|
|
201
209
|
def _query_entity_data(query, id = nil, params = {})
|
202
|
-
_query(query, params).tap
|
203
|
-
response.raise_error if response.error?
|
204
|
-
end.entity_data(id)
|
210
|
+
_query(query, params).tap(&:raise_if_cypher_error!).entity_data(id)
|
205
211
|
end
|
206
212
|
|
207
213
|
def _query(query, params = {}, options = {})
|
208
214
|
query, params = query_and_params(query, params)
|
209
215
|
|
210
|
-
curr_tx = Neo4j::Transaction.current
|
211
216
|
ActiveSupport::Notifications.instrument('neo4j.cypher_query', params: params, context: options[:context],
|
212
217
|
cypher: query, pretty_cypher: options[:pretty_cypher]) do
|
213
|
-
if
|
214
|
-
|
218
|
+
if current_transaction
|
219
|
+
current_transaction._query(query, params)
|
215
220
|
else
|
216
221
|
query = params.nil? ? {'query' => query} : {'query' => query, 'params' => params}
|
217
222
|
response = @connection.post(resource_url(:cypher), query)
|
@@ -225,7 +230,7 @@ module Neo4j
|
|
225
230
|
|
226
231
|
Enumerator.new do |yielder|
|
227
232
|
response.data.each do |data|
|
228
|
-
if
|
233
|
+
if current_transaction
|
229
234
|
data[:row].each do |id|
|
230
235
|
yielder << CypherNode.new(self, id).wrapper
|
231
236
|
end
|
@@ -236,12 +241,16 @@ module Neo4j
|
|
236
241
|
end
|
237
242
|
end
|
238
243
|
|
244
|
+
def current_transaction
|
245
|
+
Neo4j::Transaction.current_for(self)
|
246
|
+
end
|
247
|
+
|
239
248
|
EMPTY = ''
|
240
249
|
NEWLINE_W_SPACES = "\n "
|
241
250
|
def self.log_with
|
242
251
|
ActiveSupport::Notifications.subscribe('neo4j.cypher_query') do |_, start, finish, _id, payload|
|
243
252
|
ms = (finish - start) * 1000
|
244
|
-
params_string = (payload[:params] && payload[:params].
|
253
|
+
params_string = (payload[:params] && !payload[:params].empty? ? "| #{payload[:params].inspect}" : EMPTY)
|
245
254
|
cypher = payload[:pretty_cypher] ? NEWLINE_W_SPACES + payload[:pretty_cypher].gsub(/\n/, NEWLINE_W_SPACES) : payload[:cypher]
|
246
255
|
|
247
256
|
yield(" #{ANSI::CYAN}#{payload[:context] || 'CYPHER'}#{ANSI::CLEAR} #{ANSI::YELLOW}#{ms.round}ms#{ANSI::CLEAR} #{cypher} #{params_string}")
|
@@ -7,16 +7,20 @@ module Neo4j
|
|
7
7
|
# * `close` is called to end the transaction. It calls `commit` or `delete`.
|
8
8
|
#
|
9
9
|
# If a transaction is created and then closed without performing any queries, an OpenStruct is returned that behaves like a successfully closed query.
|
10
|
-
class CypherTransaction
|
11
|
-
include Neo4j::Transaction::Instance
|
10
|
+
class CypherTransaction < Neo4j::Transaction::Base
|
12
11
|
include Resource
|
13
12
|
|
14
|
-
attr_reader :commit_url, :query_url
|
13
|
+
attr_reader :commit_url, :query_url
|
15
14
|
|
16
|
-
def
|
17
|
-
@
|
18
|
-
|
19
|
-
|
15
|
+
def connection
|
16
|
+
@session.connection
|
17
|
+
end
|
18
|
+
|
19
|
+
def base_url
|
20
|
+
require 'uri'
|
21
|
+
URI(@session.instance_variable_get('@resource_url')).tap do |uri|
|
22
|
+
uri.path = ''
|
23
|
+
end.to_s
|
20
24
|
end
|
21
25
|
|
22
26
|
ROW_REST = %w(row REST)
|
@@ -31,28 +35,34 @@ module Neo4j
|
|
31
35
|
end
|
32
36
|
|
33
37
|
def start(body)
|
34
|
-
request(:post,
|
38
|
+
request(:post, start_url, 201, body).tap do |response|
|
35
39
|
@commit_url = response.body[:commit]
|
36
40
|
@query_url = response.headers[:Location]
|
37
41
|
|
38
42
|
fail "NO ENDPOINT URL #{connection} : HEAD: #{response.headers.inspect}" if !@query_url || @query_url.empty?
|
39
43
|
|
40
|
-
init_resource_data(response.body,
|
44
|
+
init_resource_data(response.body, base_url)
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
48
|
+
def start_url
|
49
|
+
@session.resource_data.fetch(:transaction) || base_url
|
50
|
+
end
|
51
|
+
|
44
52
|
def query(body)
|
45
53
|
request(:post, @query_url, 200, body)
|
46
54
|
end
|
47
55
|
|
56
|
+
EMPTY_RESPONSE = OpenStruct.new(status: 200, body: '')
|
57
|
+
|
48
58
|
def delete
|
49
|
-
return
|
59
|
+
return EMPTY_RESPONSE if !@commit_url || expired?
|
50
60
|
|
51
61
|
request(:delete, @query_url, 200, nil, resource_headers)
|
52
62
|
end
|
53
63
|
|
54
64
|
def commit
|
55
|
-
return
|
65
|
+
return EMPTY_RESPONSE if !@commit_url || expired?
|
56
66
|
|
57
67
|
request(:post, @commit_url, 200, nil, resource_headers)
|
58
68
|
end
|
@@ -66,11 +76,9 @@ module Neo4j
|
|
66
76
|
end
|
67
77
|
|
68
78
|
def create_cypher_response(response)
|
69
|
-
first_result = response.body[:results][0]
|
70
|
-
|
71
79
|
CypherResponse.new(response, true).tap do |cypher_response|
|
72
80
|
if response.body[:errors].empty?
|
73
|
-
cypher_response.set_data(
|
81
|
+
cypher_response.set_data(response.body[:results][0])
|
74
82
|
else
|
75
83
|
first_error = response.body[:errors].first
|
76
84
|
tx_cleanup!(first_error)
|
@@ -81,7 +89,7 @@ module Neo4j
|
|
81
89
|
|
82
90
|
def tx_cleanup!(first_error)
|
83
91
|
autoclosed!
|
84
|
-
mark_expired if first_error[:message]
|
92
|
+
mark_expired if first_error[:message] =~ /Unrecognized transaction id/
|
85
93
|
end
|
86
94
|
|
87
95
|
def empty_response
|
@@ -16,14 +16,13 @@ module Neo4j
|
|
16
16
|
self
|
17
17
|
end
|
18
18
|
|
19
|
-
def wrap_resource(connection
|
20
|
-
|
21
|
-
CypherTransaction.new(url, connection)
|
19
|
+
def wrap_resource(connection)
|
20
|
+
CypherTransaction.new(resource_url(:transaction), connection)
|
22
21
|
end
|
23
22
|
|
24
23
|
def resource_url(key = nil)
|
25
24
|
return @resource_url if key.nil?
|
26
|
-
|
25
|
+
resource_data.fetch key
|
27
26
|
rescue KeyError
|
28
27
|
raise "No resource key '#{key}', available #{@resource_data.keys.inspect}"
|
29
28
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
1
|
module Neo4j
|
3
2
|
module Core
|
4
3
|
class CypherSession
|
4
|
+
attr_reader :adaptor
|
5
|
+
|
5
6
|
def initialize(adaptor)
|
6
7
|
fail ArgumentError, "Invalid adaptor: #{adaptor.inspect}" if !adaptor.is_a?(Adaptors::Base)
|
7
8
|
|
@@ -10,22 +11,29 @@ module Neo4j
|
|
10
11
|
@adaptor.connect
|
11
12
|
end
|
12
13
|
|
14
|
+
def transaction_class
|
15
|
+
Neo4j::Core::CypherSession::Transactions::Base
|
16
|
+
end
|
17
|
+
|
18
|
+
%w(
|
19
|
+
version
|
20
|
+
).each do |method, &_block|
|
21
|
+
define_method(method) do |*args, &block|
|
22
|
+
@adaptor.send(method, *args, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
13
26
|
%w(
|
14
27
|
query
|
15
28
|
queries
|
16
29
|
|
17
|
-
start_transaction
|
18
|
-
end_transaction
|
19
30
|
transaction
|
20
|
-
transaction_started?
|
21
31
|
|
22
|
-
|
23
|
-
|
24
|
-
indexes_for_label
|
25
|
-
uniqueness_constraints_for_label
|
32
|
+
indexes
|
33
|
+
constraints
|
26
34
|
).each do |method, &_block|
|
27
35
|
define_method(method) do |*args, &block|
|
28
|
-
@adaptor.send(method, *args, &block)
|
36
|
+
@adaptor.send(method, self, *args, &block)
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
@@ -1,19 +1,61 @@
|
|
1
1
|
require 'neo4j/core/cypher_session'
|
2
2
|
require 'neo4j/core/instrumentable'
|
3
|
+
require 'neo4j/core/label'
|
3
4
|
|
4
5
|
module Neo4j
|
5
6
|
module Core
|
6
7
|
class CypherSession
|
8
|
+
class CypherError < StandardError
|
9
|
+
attr_reader :code, :message, :stack_trace
|
10
|
+
|
11
|
+
def self.new_from(code, message, stack_trace = nil)
|
12
|
+
@code = code
|
13
|
+
@message = message
|
14
|
+
@stack_trace = stack_trace
|
15
|
+
|
16
|
+
msg = <<-ERROR
|
17
|
+
Cypher error:
|
18
|
+
#{ANSI::CYAN}#{code}#{ANSI::CLEAR}: #{message}
|
19
|
+
#{stack_trace}
|
20
|
+
ERROR
|
21
|
+
|
22
|
+
error_class_from(code).new(msg)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.error_class_from(code)
|
26
|
+
case code
|
27
|
+
when /(ConstraintValidationFailed|ConstraintViolation)/
|
28
|
+
SchemaErrors::ConstraintValidationFailedError
|
29
|
+
else
|
30
|
+
CypherError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
module SchemaErrors
|
35
|
+
class ConstraintValidationFailedError < CypherError; end
|
36
|
+
end
|
37
|
+
|
7
38
|
module Adaptors
|
8
39
|
MAP = {}
|
9
40
|
|
10
41
|
class Base
|
11
42
|
include Neo4j::Core::Instrumentable
|
12
43
|
|
44
|
+
gem, version = if defined?(::Neo4j::ActiveNode)
|
45
|
+
['neo4j', ::Neo4j::VERSION]
|
46
|
+
else
|
47
|
+
['neo4j-core', ::Neo4j::Core::VERSION]
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
USER_AGENT_STRING = "#{gem}-gem/#{version} (https://github.com/neo4jrb/#{gem})"
|
52
|
+
|
13
53
|
def connect(*_args)
|
14
54
|
fail '#connect not implemented!'
|
15
55
|
end
|
16
56
|
|
57
|
+
attr_accessor :wrap_level
|
58
|
+
|
17
59
|
Query = Struct.new(:cypher, :parameters, :pretty_cypher, :context)
|
18
60
|
|
19
61
|
class QueryBuilder
|
@@ -43,57 +85,71 @@ module Neo4j
|
|
43
85
|
end
|
44
86
|
end
|
45
87
|
|
46
|
-
def query(*args)
|
47
|
-
|
88
|
+
def query(session, *args)
|
89
|
+
options = (args.size == 3 || (args[0].is_a?(::Neo4j::Core::Query) && args.size == 2)) ? args.pop : {}
|
90
|
+
|
91
|
+
queries(session, options) { append(*args) }[0]
|
48
92
|
end
|
49
93
|
|
50
|
-
def queries(&block)
|
94
|
+
def queries(session, options = {}, &block)
|
51
95
|
query_builder = QueryBuilder.new
|
52
96
|
|
53
97
|
query_builder.instance_eval(&block)
|
54
98
|
|
55
|
-
|
99
|
+
new_or_current_transaction(session, options[:transaction]) do |tx|
|
100
|
+
query_set(tx, query_builder.queries, {commit: !options[:transaction]}.merge(options))
|
101
|
+
end
|
56
102
|
end
|
57
103
|
|
58
|
-
|
59
|
-
|
104
|
+
[:query_set,
|
105
|
+
:version,
|
106
|
+
:indexes,
|
107
|
+
:constraints,
|
108
|
+
:connected?].each do |method|
|
109
|
+
define_method(method) do |*_args|
|
110
|
+
fail "##{method} method not implemented on adaptor!"
|
111
|
+
end
|
60
112
|
end
|
61
113
|
|
62
|
-
|
63
|
-
|
64
|
-
|
114
|
+
# If called without a block, returns a Transaction object
|
115
|
+
# which can be used to call query/queries/mark_failed/commit
|
116
|
+
# If called with a block, the Transaction object is yielded
|
117
|
+
# to the block and `commit` is ensured. Any uncaught exceptions
|
118
|
+
# will mark the transaction as failed first
|
119
|
+
def transaction(session)
|
120
|
+
return self.class.transaction_class.new(session) if !block_given?
|
65
121
|
|
66
|
-
|
67
|
-
|
68
|
-
end
|
122
|
+
begin
|
123
|
+
tx = transaction(session)
|
69
124
|
|
70
|
-
|
71
|
-
|
72
|
-
|
125
|
+
yield tx
|
126
|
+
rescue => e
|
127
|
+
tx.mark_failed
|
73
128
|
|
74
|
-
|
75
|
-
|
129
|
+
raise e
|
130
|
+
ensure
|
131
|
+
tx.close
|
132
|
+
end
|
76
133
|
end
|
77
134
|
|
78
|
-
|
79
|
-
|
80
|
-
fail '#indexes_for_label not implemented!'
|
81
|
-
end
|
135
|
+
def logger
|
136
|
+
return @logger if @logger
|
82
137
|
|
83
|
-
|
84
|
-
|
138
|
+
@logger = if @options[:logger]
|
139
|
+
@options[:logger]
|
140
|
+
else
|
141
|
+
Logger.new(logger_location).tap do |logger|
|
142
|
+
logger.level = logger_level
|
143
|
+
end
|
144
|
+
end
|
85
145
|
end
|
86
146
|
|
147
|
+
def setup_queries!(queries, transaction, options = {})
|
148
|
+
fail 'Query attempted without a connection' if !connected?
|
149
|
+
fail "Invalid transaction object: #{transaction.inspect}" if !transaction.is_a?(self.class.transaction_class)
|
87
150
|
|
88
|
-
|
89
|
-
|
90
|
-
# full transaction
|
91
|
-
def transaction
|
92
|
-
start_transaction
|
93
|
-
|
94
|
-
yield
|
95
|
-
ensure
|
96
|
-
end_transaction if transaction_started?
|
151
|
+
# context option not yet implemented
|
152
|
+
self.class.instrument_queries(queries) unless options[:skip_instrumentation]
|
97
153
|
end
|
98
154
|
|
99
155
|
EMPTY = ''
|
@@ -101,7 +157,7 @@ module Neo4j
|
|
101
157
|
|
102
158
|
instrument(:query, 'neo4j.core.cypher_query', %w(query)) do |_, _start, _finish, _id, payload|
|
103
159
|
query = payload[:query]
|
104
|
-
params_string = (query.parameters && query.parameters.
|
160
|
+
params_string = (query.parameters && !query.parameters.empty? ? "| #{query.parameters.inspect}" : EMPTY)
|
105
161
|
cypher = query.pretty_cypher ? NEWLINE_W_SPACES + query.pretty_cypher.gsub(/\n/, NEWLINE_W_SPACES) : query.cypher
|
106
162
|
|
107
163
|
" #{ANSI::CYAN}#{query.context || 'CYPHER'}#{ANSI::CLEAR} #{cypher} #{params_string}"
|
@@ -113,6 +169,33 @@ module Neo4j
|
|
113
169
|
instrument_query(query) {}
|
114
170
|
end
|
115
171
|
end
|
172
|
+
|
173
|
+
def transaction_class
|
174
|
+
fail '.transaction_class method not implemented on adaptor!'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def new_or_current_transaction(session, tx, &block)
|
181
|
+
if tx
|
182
|
+
yield(tx)
|
183
|
+
else
|
184
|
+
transaction(session, &block)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def validate_query_set!(transaction, _queries, _options = {})
|
189
|
+
fail 'Query attempted without a connection' if !connected?
|
190
|
+
fail "Invalid transaction object: #{transaction}" if !transaction.is_a?(self.class.transaction_class)
|
191
|
+
end
|
192
|
+
|
193
|
+
def logger_location
|
194
|
+
@options[:logger_location] || STDOUT
|
195
|
+
end
|
196
|
+
|
197
|
+
def logger_level
|
198
|
+
@options[:logger_level] || Logger::WARN
|
116
199
|
end
|
117
200
|
end
|
118
201
|
end
|