activegraph 10.0.0.pre.alpha.6

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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1989 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +24 -0
  5. data/README.md +107 -0
  6. data/bin/rake +17 -0
  7. data/config/locales/en.yml +5 -0
  8. data/config/neo4j/add_classnames.yml +1 -0
  9. data/config/neo4j/config.yml +38 -0
  10. data/lib/neo4j.rb +116 -0
  11. data/lib/neo4j/active_base.rb +89 -0
  12. data/lib/neo4j/active_node.rb +108 -0
  13. data/lib/neo4j/active_node/callbacks.rb +8 -0
  14. data/lib/neo4j/active_node/dependent.rb +11 -0
  15. data/lib/neo4j/active_node/dependent/association_methods.rb +49 -0
  16. data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +51 -0
  17. data/lib/neo4j/active_node/enum.rb +26 -0
  18. data/lib/neo4j/active_node/has_n.rb +612 -0
  19. data/lib/neo4j/active_node/has_n/association.rb +278 -0
  20. data/lib/neo4j/active_node/has_n/association/rel_factory.rb +61 -0
  21. data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +23 -0
  22. data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +108 -0
  23. data/lib/neo4j/active_node/id_property.rb +224 -0
  24. data/lib/neo4j/active_node/id_property/accessor.rb +62 -0
  25. data/lib/neo4j/active_node/initialize.rb +21 -0
  26. data/lib/neo4j/active_node/labels.rb +207 -0
  27. data/lib/neo4j/active_node/labels/index.rb +37 -0
  28. data/lib/neo4j/active_node/labels/reloading.rb +21 -0
  29. data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
  30. data/lib/neo4j/active_node/node_wrapper.rb +54 -0
  31. data/lib/neo4j/active_node/orm_adapter.rb +82 -0
  32. data/lib/neo4j/active_node/persistence.rb +187 -0
  33. data/lib/neo4j/active_node/property.rb +60 -0
  34. data/lib/neo4j/active_node/query.rb +76 -0
  35. data/lib/neo4j/active_node/query/query_proxy.rb +374 -0
  36. data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +177 -0
  37. data/lib/neo4j/active_node/query/query_proxy_eager_loading/association_tree.rb +75 -0
  38. data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +110 -0
  39. data/lib/neo4j/active_node/query/query_proxy_find_in_batches.rb +19 -0
  40. data/lib/neo4j/active_node/query/query_proxy_link.rb +139 -0
  41. data/lib/neo4j/active_node/query/query_proxy_methods.rb +302 -0
  42. data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +86 -0
  43. data/lib/neo4j/active_node/query_methods.rb +68 -0
  44. data/lib/neo4j/active_node/reflection.rb +86 -0
  45. data/lib/neo4j/active_node/rels.rb +11 -0
  46. data/lib/neo4j/active_node/scope.rb +166 -0
  47. data/lib/neo4j/active_node/unpersisted.rb +48 -0
  48. data/lib/neo4j/active_node/validations.rb +59 -0
  49. data/lib/neo4j/active_rel.rb +67 -0
  50. data/lib/neo4j/active_rel/callbacks.rb +15 -0
  51. data/lib/neo4j/active_rel/initialize.rb +28 -0
  52. data/lib/neo4j/active_rel/persistence.rb +134 -0
  53. data/lib/neo4j/active_rel/persistence/query_factory.rb +95 -0
  54. data/lib/neo4j/active_rel/property.rb +95 -0
  55. data/lib/neo4j/active_rel/query.rb +101 -0
  56. data/lib/neo4j/active_rel/rel_wrapper.rb +31 -0
  57. data/lib/neo4j/active_rel/related_node.rb +87 -0
  58. data/lib/neo4j/active_rel/types.rb +82 -0
  59. data/lib/neo4j/active_rel/validations.rb +8 -0
  60. data/lib/neo4j/ansi.rb +14 -0
  61. data/lib/neo4j/class_arguments.rb +39 -0
  62. data/lib/neo4j/config.rb +135 -0
  63. data/lib/neo4j/core.rb +14 -0
  64. data/lib/neo4j/core/connection_failed_error.rb +6 -0
  65. data/lib/neo4j/core/cypher_error.rb +37 -0
  66. data/lib/neo4j/core/driver.rb +66 -0
  67. data/lib/neo4j/core/has_uri.rb +63 -0
  68. data/lib/neo4j/core/instrumentable.rb +36 -0
  69. data/lib/neo4j/core/label.rb +158 -0
  70. data/lib/neo4j/core/logging.rb +44 -0
  71. data/lib/neo4j/core/node.rb +23 -0
  72. data/lib/neo4j/core/querable.rb +88 -0
  73. data/lib/neo4j/core/query.rb +487 -0
  74. data/lib/neo4j/core/query_builder.rb +32 -0
  75. data/lib/neo4j/core/query_clauses.rb +727 -0
  76. data/lib/neo4j/core/query_ext.rb +24 -0
  77. data/lib/neo4j/core/query_find_in_batches.rb +49 -0
  78. data/lib/neo4j/core/relationship.rb +13 -0
  79. data/lib/neo4j/core/responses.rb +50 -0
  80. data/lib/neo4j/core/result.rb +33 -0
  81. data/lib/neo4j/core/schema.rb +30 -0
  82. data/lib/neo4j/core/schema_errors.rb +12 -0
  83. data/lib/neo4j/core/wrappable.rb +30 -0
  84. data/lib/neo4j/errors.rb +57 -0
  85. data/lib/neo4j/migration.rb +148 -0
  86. data/lib/neo4j/migrations.rb +27 -0
  87. data/lib/neo4j/migrations/base.rb +77 -0
  88. data/lib/neo4j/migrations/check_pending.rb +20 -0
  89. data/lib/neo4j/migrations/helpers.rb +105 -0
  90. data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
  91. data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
  92. data/lib/neo4j/migrations/helpers/schema.rb +51 -0
  93. data/lib/neo4j/migrations/migration_file.rb +24 -0
  94. data/lib/neo4j/migrations/runner.rb +195 -0
  95. data/lib/neo4j/migrations/schema.rb +44 -0
  96. data/lib/neo4j/migrations/schema_migration.rb +14 -0
  97. data/lib/neo4j/model_schema.rb +139 -0
  98. data/lib/neo4j/paginated.rb +27 -0
  99. data/lib/neo4j/railtie.rb +105 -0
  100. data/lib/neo4j/schema/operation.rb +102 -0
  101. data/lib/neo4j/shared.rb +60 -0
  102. data/lib/neo4j/shared/attributes.rb +216 -0
  103. data/lib/neo4j/shared/callbacks.rb +68 -0
  104. data/lib/neo4j/shared/cypher.rb +37 -0
  105. data/lib/neo4j/shared/declared_properties.rb +204 -0
  106. data/lib/neo4j/shared/declared_property.rb +109 -0
  107. data/lib/neo4j/shared/declared_property/index.rb +37 -0
  108. data/lib/neo4j/shared/enum.rb +167 -0
  109. data/lib/neo4j/shared/filtered_hash.rb +79 -0
  110. data/lib/neo4j/shared/identity.rb +34 -0
  111. data/lib/neo4j/shared/initialize.rb +64 -0
  112. data/lib/neo4j/shared/marshal.rb +23 -0
  113. data/lib/neo4j/shared/mass_assignment.rb +64 -0
  114. data/lib/neo4j/shared/permitted_attributes.rb +28 -0
  115. data/lib/neo4j/shared/persistence.rb +282 -0
  116. data/lib/neo4j/shared/property.rb +240 -0
  117. data/lib/neo4j/shared/query_factory.rb +102 -0
  118. data/lib/neo4j/shared/rel_type_converters.rb +43 -0
  119. data/lib/neo4j/shared/serialized_properties.rb +30 -0
  120. data/lib/neo4j/shared/type_converters.rb +433 -0
  121. data/lib/neo4j/shared/typecasted_attributes.rb +98 -0
  122. data/lib/neo4j/shared/typecaster.rb +53 -0
  123. data/lib/neo4j/shared/validations.rb +44 -0
  124. data/lib/neo4j/tasks/migration.rake +202 -0
  125. data/lib/neo4j/timestamps.rb +11 -0
  126. data/lib/neo4j/timestamps/created.rb +9 -0
  127. data/lib/neo4j/timestamps/updated.rb +9 -0
  128. data/lib/neo4j/transaction.rb +139 -0
  129. data/lib/neo4j/type_converters.rb +7 -0
  130. data/lib/neo4j/undeclared_properties.rb +53 -0
  131. data/lib/neo4j/version.rb +3 -0
  132. data/lib/neo4j/wrapper.rb +4 -0
  133. data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
  134. data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
  135. data/lib/rails/generators/neo4j/model/model_generator.rb +88 -0
  136. data/lib/rails/generators/neo4j/model/templates/migration.erb +9 -0
  137. data/lib/rails/generators/neo4j/model/templates/model.erb +15 -0
  138. data/lib/rails/generators/neo4j/upgrade_v8/templates/migration.erb +17 -0
  139. data/lib/rails/generators/neo4j/upgrade_v8/upgrade_v8_generator.rb +32 -0
  140. data/lib/rails/generators/neo4j_generator.rb +119 -0
  141. data/neo4j.gemspec +51 -0
  142. metadata +421 -0
@@ -0,0 +1,66 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'neo4j/core/logging'
3
+ require 'neo4j/core/has_uri'
4
+ require 'neo4j/version'
5
+
6
+ module Neo4j
7
+ module Core
8
+ class Driver
9
+ include HasUri
10
+
11
+ USER_AGENT_STRING = "neo4j-gem/#{::Neo4j::VERSION} (https://github.com/neo4jrb/neo4j)"
12
+
13
+ attr_accessor :wrap_level
14
+ attr_reader :options, :driver
15
+ delegate :close, to: :driver
16
+
17
+ default_url('bolt://neo4:neo4j@localhost:7687')
18
+
19
+ validate_uri do |uri|
20
+ uri.scheme == 'bolt'
21
+ end
22
+
23
+ class << self
24
+ def new_instance(url)
25
+ uri = URI(url)
26
+ user = uri.user
27
+ password = uri.password
28
+ auth_token = if user
29
+ Neo4j::Driver::AuthTokens.basic(user, password)
30
+ else
31
+ Neo4j::Driver::AuthTokens.none
32
+ end
33
+ Neo4j::Driver::GraphDatabase.driver(url, auth_token)
34
+ end
35
+ end
36
+
37
+ def initialize(url, options = {})
38
+ self.url = url
39
+ @driver = self.class.new_instance(url)
40
+ @options = options
41
+ end
42
+
43
+ def logger
44
+ return @logger if @logger
45
+
46
+ @logger = if @options[:logger]
47
+ @options[:logger]
48
+ else
49
+ Logger.new(logger_location).tap do |logger|
50
+ logger.level = logger_level
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def logger_location
58
+ @options[:logger_location] || STDOUT
59
+ end
60
+
61
+ def logger_level
62
+ @options[:logger_level] || Logger::WARN
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,63 @@
1
+ require 'active_support/concern'
2
+
3
+ module Neo4j
4
+ module Core
5
+ # Containing the logic for dealing with adaptors which use URIs
6
+ module HasUri
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ %w[scheme user password host port].each do |method|
11
+ define_method(method) do
12
+ (@uri && @uri.send(method)) || (self.class.default_uri && self.class.default_uri.send(method))
13
+ end
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ attr_reader :default_uri
19
+
20
+ def default_url(default_url)
21
+ @default_uri = uri_from_url!(default_url)
22
+ end
23
+
24
+ def validate_uri(&block)
25
+ @uri_validator = block
26
+ end
27
+
28
+ def uri_from_url!(url)
29
+ validate_url!(url)
30
+
31
+ @uri = url.nil? ? @default_uri : URI(url)
32
+
33
+ fail ArgumentError, "Invalid URL: #{url.inspect}" if uri_valid?(@uri)
34
+
35
+ @uri
36
+ end
37
+
38
+ private
39
+
40
+ def validate_url!(url)
41
+ fail ArgumentError, "Invalid URL: #{url.inspect}" if !(url.is_a?(String) || url.nil?)
42
+ fail ArgumentError, 'No URL or default URL specified' if url.nil? && @default_uri.nil?
43
+ end
44
+
45
+ def uri_valid?(uri)
46
+ @uri_validator && !@uri_validator.call(uri)
47
+ end
48
+ end
49
+
50
+ def url
51
+ @uri.to_s
52
+ end
53
+
54
+ def url=(url)
55
+ @uri = self.class.uri_from_url!(url)
56
+ end
57
+
58
+ def url_without_password
59
+ @url_without_password ||= "#{scheme}://#{user + ':...@' if user}#{host}:#{port}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/notifications'
3
+ require 'neo4j/ansi'
4
+
5
+ module Neo4j
6
+ module Core
7
+ module Instrumentable
8
+ extend ActiveSupport::Concern
9
+
10
+ EMPTY = ''
11
+ NEWLINE_W_SPACES = "\n "
12
+
13
+ class_methods do
14
+ def subscribe_to_request
15
+ ActiveSupport::Notifications.subscribe('neo4j.core.bolt.request') do |_, start, finish, _id, _payload|
16
+ ms = (finish - start) * 1000
17
+ yield " #{ANSI::BLUE}BOLT:#{ANSI::CLEAR} #{ANSI::YELLOW}#{ms.round}ms#{ANSI::CLEAR} #{ActiveBase.current_driver.url_without_password}"
18
+ end
19
+ end
20
+
21
+ def subscribe_to_query
22
+ ActiveSupport::Notifications.subscribe('neo4j.core.cypher_query') do |_, _start, _finish, _id, payload|
23
+ query = payload[:query]
24
+ params_string = (query.parameters && !query.parameters.empty? ? "| #{query.parameters.inspect}" : EMPTY)
25
+ cypher = query.pretty_cypher ? (NEWLINE_W_SPACES if query.pretty_cypher.include?("\n")).to_s + query.pretty_cypher.gsub(/\n/, NEWLINE_W_SPACES) : query.cypher
26
+
27
+ source_line, line_number = Logging.first_external_path_and_line(caller_locations)
28
+
29
+ yield " #{ANSI::CYAN}#{query.context || 'CYPHER'}#{ANSI::CLEAR} #{cypher} #{params_string}" +
30
+ ("\n ↳ #{source_line}:#{line_number}" if ActiveBase.current_driver.options[:verbose_query_logs] && source_line).to_s
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,158 @@
1
+ module Neo4j
2
+ module Core
3
+ class Label
4
+ attr_reader :name
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def create_index(property, options = {})
11
+ validate_index_options!(options)
12
+ properties = property.is_a?(Array) ? property.join(',') : property
13
+ schema_query("CREATE INDEX ON :`#{@name}`(#{properties})")
14
+ end
15
+
16
+ def drop_index(property, options = {})
17
+ validate_index_options!(options)
18
+ schema_query("DROP INDEX ON :`#{@name}`(#{property})")
19
+ end
20
+
21
+ # Creates a neo4j constraint on a property
22
+ # See http://docs.neo4j.org/chunked/stable/query-constraints.html
23
+ # @example
24
+ # label = Neo4j::Label.create(:person, session)
25
+ # label.create_constraint(:name, {type: :unique}, session)
26
+ #
27
+ def create_constraint(property, constraints)
28
+ cypher = case constraints[:type]
29
+ when :unique, :uniqueness
30
+ "CREATE CONSTRAINT ON (n:`#{name}`) ASSERT n.`#{property}` IS UNIQUE"
31
+ else
32
+ fail "Not supported constraint #{constraints.inspect} for property #{property} (expected :type => :unique)"
33
+ end
34
+ schema_query(cypher)
35
+ end
36
+
37
+ def create_uniqueness_constraint(property, options = {})
38
+ create_constraint(property, options.merge(type: :unique))
39
+ end
40
+
41
+ # Drops a neo4j constraint on a property
42
+ # See http://docs.neo4j.org/chunked/stable/query-constraints.html
43
+ # @example
44
+ # label = Neo4j::Label.create(:person, session)
45
+ # label.create_constraint(:name, {type: :unique}, session)
46
+ # label.drop_constraint(:name, {type: :unique}, session)
47
+ #
48
+ def drop_constraint(property, constraint)
49
+ cypher = case constraint[:type]
50
+ when :unique, :uniqueness
51
+ "DROP CONSTRAINT ON (n:`#{name}`) ASSERT n.`#{property}` IS UNIQUE"
52
+ else
53
+ fail "Not supported constraint #{constraint.inspect}"
54
+ end
55
+ schema_query(cypher)
56
+ end
57
+
58
+ def drop_uniqueness_constraint(property, options = {})
59
+ drop_constraint(property, options.merge(type: :unique))
60
+ end
61
+
62
+ def indexes
63
+ self.class.indexes.select do |definition|
64
+ definition[:label] == @name.to_sym
65
+ end
66
+ end
67
+
68
+ def self.indexes
69
+ Neo4j::Transaction.indexes
70
+ end
71
+
72
+ def drop_indexes
73
+ self.class.drop_indexes
74
+ end
75
+
76
+ def self.drop_indexes
77
+ indexes.each do |definition|
78
+ begin
79
+ Neo4j::Transaction.query("DROP INDEX ON :`#{definition[:label]}`(#{definition[:properties][0]})")
80
+ rescue Neo4j::Server::CypherResponse::ResponseError
81
+ # This will error on each constraint. Ignore and continue.
82
+ next
83
+ end
84
+ end
85
+ end
86
+
87
+ def index?(property)
88
+ indexes.any? { |definition| definition[:properties] == [property.to_sym] }
89
+ end
90
+
91
+ def constraints(_options = {})
92
+ Neo4j::Transaction.constraints.select do |definition|
93
+ definition[:label] == @name.to_sym
94
+ end
95
+ end
96
+
97
+ def uniqueness_constraints(_options = {})
98
+ constraints.select do |definition|
99
+ definition[:type] == :uniqueness
100
+ end
101
+ end
102
+
103
+ def drop_uniqueness_constraints
104
+ self.class.drop_uniqueness_constraints
105
+ end
106
+
107
+ def self.drop_uniqueness_constraints
108
+ Neo4j::Transaction.constraints.each do |definition|
109
+ Neo4j::Transaction.query("DROP CONSTRAINT ON (n:`#{definition[:label]}`) ASSERT n.`#{definition[:properties][0]}` IS UNIQUE")
110
+ end
111
+ end
112
+
113
+ def constraint?(property)
114
+ constraints.any? { |definition| definition[:properties] == [property.to_sym] }
115
+ end
116
+
117
+ def uniqueness_constraint?(property)
118
+ uniqueness_constraints.include?([property])
119
+ end
120
+
121
+ def self.wait_for_schema_changes
122
+ schema_threads.map(&:join)
123
+ set_schema_threads(session, [])
124
+ end
125
+
126
+ private
127
+
128
+ # Store schema threads on the session so that we can easily wait for all
129
+ # threads on a session regardless of label
130
+ def schema_threads
131
+ self.class.schema_threads
132
+ end
133
+
134
+ def schema_threads=(array)
135
+ self.class.set_schema_threads(array)
136
+ end
137
+
138
+ class << self
139
+ def schema_threads
140
+ Neo4j::Transaction.instance_variable_get('@_schema_threads') || []
141
+ end
142
+
143
+ def set_schema_threads(array)
144
+ Neo4j::Transaction.instance_variable_set('@_schema_threads', array)
145
+ end
146
+ end
147
+
148
+ def schema_query(cypher)
149
+ Neo4j::Transaction.transaction { |tx| tx.query(cypher, {}) }
150
+ end
151
+
152
+ def validate_index_options!(options)
153
+ return unless options[:type] && options[:type] != :exact
154
+ fail "Type #{options[:type]} is not supported"
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,44 @@
1
+ # Copied largely from activerecord/lib/active_record/log_subscriber.rb
2
+ module Neo4j
3
+ module Core
4
+ module Logging
5
+ class << self
6
+ def first_external_path_and_line(callstack)
7
+ line = callstack.find do |frame|
8
+ frame.absolute_path && !ignored_callstack(frame.absolute_path)
9
+ end
10
+
11
+ offending_line = line || callstack.first
12
+
13
+ [offending_line.path,
14
+ offending_line.lineno]
15
+ end
16
+
17
+ NEO4J_CORE_GEM_ROOT = File.expand_path('../../..', __dir__) + '/'
18
+
19
+ def ignored_callstack(path)
20
+ paths_to_ignore.any?(&path.method(:start_with?))
21
+ end
22
+
23
+ def paths_to_ignore
24
+ @paths_to_ignore ||= [NEO4J_CORE_GEM_ROOT,
25
+ RbConfig::CONFIG['rubylibdir'],
26
+ neo4j_gem_path,
27
+ active_support_gem_path].compact
28
+ end
29
+
30
+ def neo4j_gem_path
31
+ return if !defined?(::Rails.root)
32
+
33
+ @neo4j_gem_path ||= File.expand_path('../../..', Neo4j::ActiveBase.method(:current_driver).source_location[0])
34
+ end
35
+
36
+ def active_support_gem_path
37
+ return if !defined?(::ActiveSupport::Notifications)
38
+
39
+ @active_support_gem_path ||= File.expand_path('../../..', ActiveSupport::Notifications.method(:subscribe).source_location[0])
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ require 'neo4j/core/wrappable'
2
+
3
+ module Neo4j
4
+ module Core
5
+ module Node
6
+ def props; properties; end
7
+ # Perhaps we should deprecate this?
8
+ def neo_id; id; end
9
+
10
+ def ==(other)
11
+ other.is_a?(Node) && neo_id == other.neo_id
12
+ end
13
+
14
+ def labels
15
+ @labels ||= super
16
+ end
17
+
18
+ def properties
19
+ @properties ||= super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,88 @@
1
+ require 'neo4j/core/instrumentable'
2
+ require 'neo4j/transaction'
3
+ require 'neo4j/core/query_builder'
4
+ require 'neo4j/core/responses'
5
+
6
+ module Neo4j
7
+ module Core
8
+ module Querable
9
+ extend ActiveSupport::Concern
10
+ include Instrumentable
11
+ include Responses
12
+
13
+ class_methods do
14
+ def query(*args)
15
+ options = case args.size
16
+ when 3
17
+ args.pop
18
+ when 2
19
+ args.pop if args[0].is_a?(::Neo4j::Core::Query)
20
+ end || {}
21
+
22
+ queries(options) { append(*args) }[0]
23
+ end
24
+
25
+ def queries(options = {}, &block)
26
+ query_builder = QueryBuilder.new
27
+
28
+ query_builder.instance_eval(&block)
29
+
30
+ new_or_current_transaction(options[:transaction]) do |tx|
31
+ query_set(tx, query_builder.queries, { commit: !options[:transaction] }.merge(options))
32
+ end
33
+ end
34
+
35
+ # If called without a block, returns a Transaction object
36
+ # which can be used to call query/queries/mark_failed/commit
37
+ # If called with a block, the Transaction object is yielded
38
+ # to the block and `commit` is ensured. Any uncaught exceptions
39
+ # will mark the transaction as failed first
40
+ def transaction
41
+ return Transaction.new unless block_given?
42
+
43
+ begin
44
+ tx = transaction
45
+
46
+ yield tx
47
+ rescue => e
48
+ tx.mark_failed if tx
49
+
50
+ raise e
51
+ ensure
52
+ tx.close if tx
53
+ end
54
+ end
55
+
56
+ def setup_queries!(queries, options = {})
57
+ return if options[:skip_instrumentation]
58
+ queries.each do |query|
59
+ ActiveSupport::Notifications.instrument('neo4j.core.cypher_query', query: query)
60
+ end
61
+ end
62
+
63
+ def query_set(transaction, queries, options = {})
64
+ setup_queries!(queries, skip_instrumentation: options[:skip_instrumentation])
65
+
66
+ ActiveSupport::Notifications.instrument('neo4j.core.bolt.request') do
67
+ self.wrap_level = options[:wrap_level]
68
+ queries.map do |query|
69
+ result_from_data(transaction.root_tx.run(query.cypher, query.parameters))
70
+ end
71
+ rescue Neo4j::Driver::Exceptions::Neo4jException => e
72
+ raise Neo4j::Core::CypherError.new_from(e.code, e.message) # , e.stack_track.to_a
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def new_or_current_transaction(tx, &block)
79
+ if tx
80
+ yield(tx)
81
+ else
82
+ transaction(&block)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end