neo4j-core 6.1.6 → 7.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|