activegraph 11.5.0.alpha.1 → 12.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -1
  3. data/Gemfile +0 -4
  4. data/activegraph.gemspec +3 -4
  5. data/lib/active_graph/base.rb +4 -0
  6. data/lib/active_graph/core/element.rb +142 -0
  7. data/lib/active_graph/core/entity.rb +4 -0
  8. data/lib/active_graph/core/label.rb +5 -166
  9. data/lib/active_graph/core/node.rb +0 -4
  10. data/lib/active_graph/core/query_clauses.rb +4 -4
  11. data/lib/active_graph/core/schema.rb +23 -28
  12. data/lib/active_graph/core/type.rb +13 -0
  13. data/lib/active_graph/migrations/helpers/schema.rb +10 -13
  14. data/lib/active_graph/model_schema.rb +1 -1
  15. data/lib/active_graph/node/has_n.rb +6 -2
  16. data/lib/active_graph/node/labels.rb +15 -12
  17. data/lib/active_graph/node/persistence.rb +0 -11
  18. data/lib/active_graph/node/query/query_proxy/link.rb +15 -4
  19. data/lib/active_graph/node/query/query_proxy.rb +3 -3
  20. data/lib/active_graph/node/query/query_proxy_eager_loading.rb +1 -1
  21. data/lib/active_graph/node/query/query_proxy_enumerable.rb +4 -4
  22. data/lib/active_graph/node/query/query_proxy_methods.rb +14 -16
  23. data/lib/active_graph/node/query/query_proxy_methods_of_mass_updating.rb +2 -5
  24. data/lib/active_graph/node/query.rb +1 -1
  25. data/lib/active_graph/node/query_methods.rb +9 -12
  26. data/lib/active_graph/railtie.rb +13 -0
  27. data/lib/active_graph/relationship/initialize.rb +2 -2
  28. data/lib/active_graph/relationship/persistence.rb +3 -1
  29. data/lib/active_graph/relationship/property.rb +1 -5
  30. data/lib/active_graph/relationship/query.rb +14 -9
  31. data/lib/active_graph/relationship/related_node.rb +4 -8
  32. data/lib/active_graph/relationship/types.rb +8 -0
  33. data/lib/active_graph/relationship/wrapping.rb +1 -1
  34. data/lib/active_graph/relationship.rb +4 -1
  35. data/lib/active_graph/shared/identity.rb +6 -3
  36. data/lib/active_graph/shared/persistence.rb +12 -1
  37. data/lib/active_graph/shared/query_factory.rb +1 -1
  38. data/lib/active_graph/shared/type_converters.rb +3 -2
  39. data/lib/active_graph/transactions.rb +4 -0
  40. data/lib/active_graph/version.rb +1 -1
  41. data/lib/active_graph.rb +2 -14
  42. data/lib/{active_graph/generators → rails/generators/active_graph/migration}/migration_generator.rb +5 -2
  43. data/lib/{active_graph/generators → rails/generators/active_graph/model}/model_generator.rb +5 -2
  44. data/lib/{active_graph/generators → rails/generators/active_graph/upgrade_v8}/upgrade_v8_generator.rb +5 -2
  45. data/lib/{active_graph → rails}/generators/migration_helper.rb +57 -0
  46. data/lib/{active_graph → rails}/generators/source_path_helper.rb +1 -1
  47. metadata +34 -54
  48. data/lib/active_graph/generators/active_model.rb +0 -33
  49. data/lib/active_graph/generators/generated_attribute.rb +0 -17
  50. /data/lib/{active_graph/generators → rails/generators/active_graph}/migration/templates/migration.erb +0 -0
  51. /data/lib/{active_graph/generators → rails/generators/active_graph}/model/templates/migration.erb +0 -0
  52. /data/lib/{active_graph/generators → rails/generators/active_graph}/model/templates/model.erb +0 -0
  53. /data/lib/{active_graph/generators → rails/generators/active_graph}/upgrade_v8/templates/migration.erb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0101891bd10ab15f40fe0b95d8f9801addbad38e6a9a620d6ed3172538f13b81'
4
- data.tar.gz: 29cd3cdd821bdd01723767210820b441d175c20722d086791e3b6f96c60e7860
3
+ metadata.gz: 5980a6fcd4bee8de9d49abdc805f45292b507d76b6d4299eb3424b57fd33dd98
4
+ data.tar.gz: 16a8d463cf9b8cf88d814b4a9fd33db8f83e92b3ab4cd2e903377e420b4acd24
5
5
  SHA512:
6
- metadata.gz: 236ae57612400438f2ea424600e5b4013790d9fe77840421727f83e5158ca4c8622cc8b2bda502d19c8f212956c86111f25b38fe5d3a68e2ef4819620432aa53
7
- data.tar.gz: e699e3c4788af542fec9c1b74552b08309a8bd3611a25232445c0bf8a7a4f292067ee3cb86db5c7ed7a34dc134eff8a1fea59c772b778a58de2b1c3d1ec47bb1
6
+ metadata.gz: 02bb5a53486be92a3a8724a42525b02148065fb0461fe9400d31c95d3bf7cbe351028cd955fea96dd22ec587baae8abe6c4e9498d131a7019bbee0bb2c78d093
7
+ data.tar.gz: a98acca7075481e24e9926bfcbb8cb6fadefc9e11cef963fa146fc7c543e8682d7fcb8639e681c3fb5971738d01568623f59456cb93ce36de7c0eaf7a6500abf
data/CHANGELOG.md CHANGED
@@ -3,10 +3,29 @@ All notable changes to this project will be documented in this file.
3
3
  This file should follow the standards specified on [http://keepachangelog.com/]
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
- ## [11.4.0] 2023-02-12
6
+ ## [12.0.0.beta.1] 2024-01-01
7
+
8
+ ## Added
9
+
10
+ - removed deprecated usage of id (neo_id), replaced with element_id, requires neo4j-ruby-driver 5
11
+ - removed the possibility of using neo_id as id_property
12
+ - added id_property to relationships
13
+
14
+ ## [11.5.0.beta.1] 2023-12-29
15
+
16
+ ## Added
17
+
18
+ - migrated to zeitwerk
19
+ - rails 7.1 support
7
20
 
8
21
  ## Fixed
9
22
 
23
+ - caching of has one relationships
24
+
25
+ ## [11.4.0] 2023-12-02
26
+
27
+ ## Added
28
+
10
29
  - Added support for cypher UNION
11
30
 
12
31
  ## [11.3.1] 2023-02-12
data/Gemfile CHANGED
@@ -2,10 +2,6 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- # gem 'neo4j-ruby-driver', path: '../neo4j-ruby-driver'
6
-
7
- # gem 'listen', '< 3.1'
8
-
9
5
  active_model_version = ENV['ACTIVE_MODEL_VERSION']
10
6
  gem 'activemodel', "~> #{active_model_version}" if active_model_version&.length&.positive?
11
7
 
data/activegraph.gemspec CHANGED
@@ -30,10 +30,9 @@ DESCRIPTION
30
30
  'bug_tracker_uri' => 'https://github.com/neo4jrb/activegraph/issues'
31
31
  }
32
32
 
33
- s.add_dependency('activemodel', '>= 4.0')
34
- s.add_dependency('activesupport', '>= 4.0')
33
+ s.add_dependency('activemodel', '>= 7')
35
34
  s.add_dependency('i18n', '!= 1.8.8') # https://github.com/jruby/jruby/issues/6547
36
- s.add_dependency('neo4j-ruby-driver', '>= 4.4.1', '< 5')
35
+ s.add_dependency('neo4j-ruby-driver', '>= 5')
37
36
  s.add_dependency('orm_adapter', '>= 0.5.0')
38
37
  s.add_dependency('sorted_set')
39
38
  s.add_development_dependency('guard')
@@ -42,7 +41,7 @@ DESCRIPTION
42
41
  s.add_development_dependency('neo4j-rake_tasks', '>= 0.3.0')
43
42
  s.add_development_dependency('os')
44
43
  s.add_development_dependency('pry')
45
- s.add_development_dependency('railties', '>= 4.0')
44
+ s.add_development_dependency('railties', '>= 7')
46
45
  s.add_development_dependency('rake')
47
46
  s.add_development_dependency('rubocop', '>= 0.56.0')
48
47
  s.add_development_dependency('yard')
@@ -60,6 +60,10 @@ module ActiveGraph
60
60
  ActiveGraph::Core::Label.new(label_name)
61
61
  end
62
62
 
63
+ def element(name, relationship: false)
64
+ (relationship ? Core::Type : Core::Label).new(name)
65
+ end
66
+
63
67
  def logger
64
68
  @logger ||= (ActiveGraph::Config[:logger] || ActiveSupport::Logger.new(STDOUT))
65
69
  end
@@ -0,0 +1,142 @@
1
+ module ActiveGraph
2
+ module Core
3
+ class Element
4
+ attr_reader :name
5
+ delegate :version?, to: ActiveGraph::Base
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ end
10
+
11
+ def create_index(*properties, **options)
12
+ validate_index_options!(options)
13
+ properties = properties.map { |p| "l.#{p}" }
14
+ schema_query("CREATE INDEX FOR (l:`#{@name}`) ON (#{properties.join('.')})")
15
+ end
16
+
17
+ def drop_index(property, options = {})
18
+ validate_index_options!(options)
19
+ schema_query("SHOW INDEXES YIELD * WHERE labelsOrTypes = $labels AND properties = $properties",
20
+ labels: [@name], properties: [property]).each do |record|
21
+ schema_query("DROP INDEX #{record[:name]}")
22
+ end
23
+ end
24
+
25
+ # Creates a neo4j constraint on a property
26
+ # See http://docs.neo4j.org/chunked/stable/query-constraints.html
27
+ # @example
28
+ # label = ActiveGraph::Label.create(:person)
29
+ # label.create_constraint(:name, {type: :unique})
30
+ #
31
+ def create_constraint(property, type: :key)
32
+ schema_query(
33
+ "CREATE CONSTRAINT #{constraint_name(property, type:)} FOR #{pattern("n:`#{name}`")} REQUIRE n.`#{property}` IS #{constraint_type(type:)}"
34
+ )
35
+ end
36
+
37
+ # Drops a neo4j constraint on a property
38
+ # See http://docs.neo4j.org/chunked/stable/query-constraints.html
39
+ # @example
40
+ # label = ActiveGraph::Label.create(:person)
41
+ # label.create_constraint(:name, {type: :unique})
42
+ # label.drop_constraint(:name, {type: :unique})
43
+ #
44
+ def drop_constraint(property, type: :key)
45
+ schema_query("DROP CONSTRAINT #{constraint_name(property, type:)} IF EXISTS")
46
+ end
47
+
48
+ def drop_uniqueness_constraint(property, options = {})
49
+ drop_constraint(property, type: :unique)
50
+ end
51
+
52
+ def indexes
53
+ self.class.indexes.select do |definition|
54
+ definition[:label] == @name.to_sym
55
+ end
56
+ end
57
+
58
+ def drop_indexes
59
+ self.class.drop_indexes
60
+ end
61
+
62
+ def index?(property)
63
+ indexes.any? { |definition| definition[:properties] == [property.to_sym] }
64
+ end
65
+
66
+ def constraints(_options = {})
67
+ ActiveGraph::Base.constraints.select do |definition|
68
+ definition[:label] == @name.to_sym
69
+ end
70
+ end
71
+
72
+ def uniqueness_constraints(_options = {})
73
+ constraints.select do |definition|
74
+ definition[:type] == :uniqueness
75
+ end
76
+ end
77
+
78
+ def constraint?(property)
79
+ constraints.any? { |definition| definition[:properties] == [property.to_sym] }
80
+ end
81
+
82
+ def uniqueness_constraint?(property)
83
+ uniqueness_constraints.include?([property])
84
+ end
85
+
86
+ private
87
+
88
+ class << self
89
+ def indexes
90
+ ActiveGraph::Base.indexes
91
+ end
92
+
93
+ def drop_indexes
94
+ indexes.each do |definition|
95
+ ActiveGraph::Base.query("DROP INDEX #{definition[:name]}") unless definition[:owningConstraint]
96
+ end
97
+ end
98
+
99
+ def drop_constraints
100
+ result = ActiveGraph::Base.read_transaction do |tx|
101
+ tx.run('SHOW CONSTRAINTS YIELD *').to_a
102
+ end
103
+ ActiveGraph::Base.write_transaction do |tx|
104
+ result.each do |record|
105
+ tx.run("DROP CONSTRAINT `#{record[:name]}`")
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def schema_query(cypher, **params)
112
+ ActiveGraph::Base.query(cypher, params)
113
+ end
114
+
115
+ def validate_index_options!(options)
116
+ return unless options[:type] && options[:type] != :exact
117
+ fail "Type #{options[:type]} is not supported"
118
+ end
119
+
120
+ def constraint_type(type:)
121
+ case symnolic_type(type:)
122
+ when :key
123
+ "#{element_type} KEY"
124
+ when :unique
125
+ "UNIQUE"
126
+ when :not_null
127
+ "UNIQUE"
128
+ else
129
+ ":: #{type.to_s.upcase}"
130
+ end
131
+ end
132
+
133
+ def symnolic_type(type:)
134
+ type == :key && !ActiveGraph::Base.enterprise? ? :unique : type
135
+ end
136
+
137
+ def constraint_name(property, type:)
138
+ "`#{element_type}_#{name}##{property}_#{symnolic_type(type:)}`"
139
+ end
140
+ end
141
+ end
142
+ end
@@ -3,6 +3,10 @@
3
3
  module ActiveGraph
4
4
  module Core
5
5
  module Entity
6
+ def neo_id
7
+ element_id
8
+ end
9
+
6
10
  def properties
7
11
  @properties ||= super
8
12
  end
@@ -1,173 +1,12 @@
1
1
  module ActiveGraph
2
2
  module Core
3
- class Label
4
- attr_reader :name
5
- delegate :version?, to: ActiveGraph::Base
6
-
7
- def initialize(name)
8
- @name = name
9
- end
10
-
11
- def create_index(*properties, **options)
12
- validate_index_options!(options)
13
- if version?('>=4.4')
14
- properties = properties.map { |p| "l.#{p}" }
15
- fragment = "FOR (l:`#{@name}`) ON"
16
- else
17
- fragment = "ON :`#{@name}`"
18
- end
19
- schema_query("CREATE INDEX #{fragment} (#{properties.join('.')})")
20
- end
21
-
22
- def drop_index(property, options = {})
23
- validate_index_options!(options)
24
- if version?('<4.3')
25
- schema_query("DROP INDEX ON :`#{@name}`(#{property})")
26
- else
27
- schema_query("SHOW INDEXES YIELD * WHERE labelsOrTypes = $labels AND properties = $properties",
28
- labels: [@name], properties: [property]).each do |record|
29
- schema_query("DROP INDEX #{record[:name]}")
30
- end
31
- end
32
- end
33
-
34
- # Creates a neo4j constraint on a property
35
- # See http://docs.neo4j.org/chunked/stable/query-constraints.html
36
- # @example
37
- # label = ActiveGraph::Label.create(:person)
38
- # label.create_constraint(:name, {type: :unique})
39
- #
40
- def create_constraint(property, constraints)
41
- cypher = case constraints[:type]
42
- when :unique, :uniqueness
43
- _for, _require = version?('>=4.4') ? %w[FOR REQUIRE] : %w[ON ASSERT]
44
- "CREATE CONSTRAINT #{_for} (n:`#{name}`) #{_require} n.`#{property}` IS UNIQUE"
45
- else
46
- fail "Not supported constraint #{constraints.inspect} for property #{property} (expected :type => :unique)"
47
- end
48
- schema_query(cypher)
49
- end
50
-
51
- def create_uniqueness_constraint(property, options = {})
52
- create_constraint(property, options.merge(type: :unique))
53
- end
54
-
55
- # Drops a neo4j constraint on a property
56
- # See http://docs.neo4j.org/chunked/stable/query-constraints.html
57
- # @example
58
- # label = ActiveGraph::Label.create(:person)
59
- # label.create_constraint(:name, {type: :unique})
60
- # label.drop_constraint(:name, {type: :unique})
61
- #
62
- def drop_constraint(property, constraint)
63
- return drop_constraint42(property, constraint) if version?('<4.3')
64
- type = case constraint[:type]
65
- when :unique, :uniqueness
66
- 'UNIQUENESS'
67
- when :exists
68
- 'NODE_PROPERTY_EXISTENCE'
69
- else
70
- fail "Not supported constraint #{constraint.inspect}"
71
- end
72
- schema_query(
73
- 'SHOW CONSTRAINTS YIELD * WHERE type = $type AND labelsOrTypes = $labels AND properties = $properties',
74
- type: type, labels: [name], properties: [property]).first[:name].tap do |constraint_name|
75
- schema_query("DROP CONSTRAINT #{constraint_name}")
76
- end
77
- end
78
-
79
- def drop_uniqueness_constraint(property, options = {})
80
- drop_constraint(property, options.merge(type: :unique))
81
- end
82
-
83
- def indexes
84
- self.class.indexes.select do |definition|
85
- definition[:label] == @name.to_sym
86
- end
87
- end
88
-
89
- def drop_indexes
90
- self.class.drop_indexes
91
- end
92
-
93
- def index?(property)
94
- indexes.any? { |definition| definition[:properties] == [property.to_sym] }
95
- end
96
-
97
- def constraints(_options = {})
98
- ActiveGraph::Base.constraints.select do |definition|
99
- definition[:label] == @name.to_sym
100
- end
101
- end
102
-
103
- def uniqueness_constraints(_options = {})
104
- constraints.select do |definition|
105
- definition[:type] == :uniqueness
106
- end
107
- end
108
-
109
- def constraint?(property)
110
- constraints.any? { |definition| definition[:properties] == [property.to_sym] }
111
- end
112
-
113
- def uniqueness_constraint?(property)
114
- uniqueness_constraints.include?([property])
115
- end
116
-
117
- private
118
-
119
- class << self
120
- def indexes
121
- ActiveGraph::Base.indexes
122
- end
123
-
124
- def drop_indexes
125
- indexes.each do |definition|
126
- begin
127
- ActiveGraph::Base.query(
128
- if definition[:name]
129
- "DROP INDEX #{definition[:name]}"
130
- else
131
- "DROP INDEX ON :`#{definition[:label]}`(#{definition[:properties][0]})"
132
- end)
133
- rescue Neo4j::Driver::Exceptions::DatabaseException
134
- # This will error on each constraint. Ignore and continue.
135
- next
136
- end
137
- end
138
- end
139
-
140
- def drop_constraints
141
- result = ActiveGraph::Base.read_transaction do |tx|
142
- tx.run(ActiveGraph::Base.version?('<4.3') ? 'CALL db.constraints' : 'SHOW CONSTRAINTS YIELD *').to_a
143
- end
144
- ActiveGraph::Base.write_transaction do |tx|
145
- result.each do |record|
146
- tx.run("DROP #{record.keys.include?(:name) ? "CONSTRAINT #{record[:name]}" : record[:description]}")
147
- end
148
- end
149
- end
150
- end
151
-
152
- def schema_query(cypher, **params)
153
- ActiveGraph::Base.query(cypher, params)
154
- end
155
-
156
- def validate_index_options!(options)
157
- return unless options[:type] && options[:type] != :exact
158
- fail "Type #{options[:type]} is not supported"
3
+ class Label < Element
4
+ def pattern(spec)
5
+ "(#{spec})"
159
6
  end
160
7
 
161
- def drop_constraint42(property, constraint)
162
- cypher = case constraint[:type]
163
- when :unique, :uniqueness
164
- "n.`#{property}` IS UNIQUE"
165
- when :exists
166
- "exists(n.`#{property}`)"
167
- else
168
- fail "Not supported constraint #{constraint.inspect}"
169
- end
170
- schema_query("DROP CONSTRAINT ON (n:`#{name}`) ASSERT #{cypher}")
8
+ def element_type
9
+ 'NODE'
171
10
  end
172
11
  end
173
12
  end
@@ -3,10 +3,6 @@
3
3
  module ActiveGraph
4
4
  module Core
5
5
  module Node
6
- def neo_id
7
- id
8
- end
9
-
10
6
  def labels
11
7
  @labels ||= super
12
8
  end
@@ -158,7 +158,7 @@ module ActiveGraph
158
158
  end
159
159
 
160
160
  def from_key_and_single_value(key, value)
161
- value.to_sym == :neo_id ? "ID(#{key})" : "#{key}.#{value}"
161
+ value.to_sym == :neo_id ? "elementId(#{key})" : "#{key}.#{value}"
162
162
  end
163
163
  end
164
164
 
@@ -200,7 +200,7 @@ module ActiveGraph
200
200
  end
201
201
 
202
202
  def array_value?(value, is_set)
203
- value.is_a?(Array) && !is_set
203
+ value.is_a?(Enumerable) && !is_set
204
204
  end
205
205
 
206
206
  def format_label(label_arg)
@@ -316,8 +316,8 @@ module ActiveGraph
316
316
  def hash_key_value_string(key, value, previous_keys)
317
317
  value.map do |k, v|
318
318
  if k.to_sym == :neo_id
319
- v = Array(v).map { |item| (item.respond_to?(:neo_id) ? item.neo_id : item).to_i }
320
- key_value_string("ID(#{key})", v)
319
+ v = Array(v).map { |item| item.respond_to?(:neo_id) ? item.neo_id : item }
320
+ key_value_string("elementId(#{key})", v)
321
321
  else
322
322
  "#{key}.#{from_key_and_value(k, v, previous_keys + [key])}"
323
323
  end
@@ -1,21 +1,20 @@
1
1
  module ActiveGraph
2
2
  module Core
3
3
  module Schema
4
- FILTER = {
5
- 3 => [:type, 'node_unique_property'],
6
- 4 => [:uniqueness, 'UNIQUE'],
7
- }
8
-
9
4
  def version
10
- @version ||= read_transaction do
11
- # BTW: community / enterprise could be retrieved via `result.first.edition`
12
- query('CALL dbms.components()', {}, skip_instrumentation: true).first[:versions][0]
13
- .then(&Gem::Version.method(:new))
14
- end
5
+ Gem::Version.new(component[:versions][0])
6
+ end
7
+
8
+ def edition
9
+ component[:edition]
10
+ end
11
+
12
+ def enterprise?
13
+ edition == 'enterprise'
15
14
  end
16
15
 
17
16
  def version?(requirement)
18
- Gem::Requirement.create(requirement).satisfied_by?(Gem::Version.new(version))
17
+ Gem::Requirement.create(requirement).satisfied_by?(version)
19
18
  end
20
19
 
21
20
  def indexes
@@ -24,17 +23,12 @@ module ActiveGraph
24
23
 
25
24
  def normalize(result, *extra)
26
25
  result.map do |row|
27
- definition(row, version?('<4') ? :index_cypher_v3 : :index_cypher)
28
- .merge(extra.to_h { |key| [key, row[key].to_sym] })
26
+ definition(row, :index_cypher).merge(extra.to_h { |key| [key, row[key].to_sym] })
29
27
  end
30
28
  end
31
29
 
32
30
  def constraints
33
- if version?('<4.3')
34
- raw_indexes.select(&method(:constraint_owned?))
35
- else
36
- raw_constraints.select(&method(:constraint_filter))
37
- end.map { |row| definition(row, :constraint_cypher).merge(type: :uniqueness) }
31
+ raw_constraints.select(&method(:constraint_filter)).map { |row| definition(row, :constraint_cypher).merge(type: :uniqueness) }
38
32
  end
39
33
 
40
34
  private def raw_constraints
@@ -45,27 +39,28 @@ module ActiveGraph
45
39
 
46
40
  def raw_indexes
47
41
  read_transaction do
48
- query(version?('<4.3') ? 'CALL db.indexes()' : 'SHOW INDEXES YIELD *', {}, skip_instrumentation: true)
49
- .reject { |row| row[:type] == 'LOOKUP' }
42
+ query('SHOW INDEXES YIELD *', {}, skip_instrumentation: true).reject { |row| row[:type] == 'LOOKUP' }
50
43
  end
51
44
  end
52
45
 
53
46
  def constraint_owned?(record)
54
- FILTER[major]&.then { |(key, value)| record[key] == value } || record[:owningConstraint]
47
+ record[:owningConstraint]
55
48
  end
56
49
 
57
50
  private
58
51
 
52
+ def component
53
+ @component ||= read_transaction do
54
+ query('CALL dbms.components()', {}, skip_instrumentation: true).first
55
+ end
56
+ end
57
+
59
58
  def major
60
59
  @major ||= version.segments.first
61
60
  end
62
61
 
63
62
  def constraint_filter(record)
64
- %w[UNIQUENESS RELATIONSHIP_PROPERTY_EXISTENCE NODE_PROPERTY_EXISTENCE NODE_KEY].include?(record[:type])
65
- end
66
-
67
- def index_cypher_v3(label, properties)
68
- "INDEX ON :#{label}#{com_sep(properties, nil)}"
63
+ %w[UNIQUENESS RELATIONSHIP_UNIQUENESS RELATIONSHIP_PROPERTY_EXISTENCE NODE_PROPERTY_EXISTENCE NODE_KEY RELATIONSHIP_KEY].include?(record[:type])
69
64
  end
70
65
 
71
66
  def index_cypher(label, properties)
@@ -82,11 +77,11 @@ module ActiveGraph
82
77
 
83
78
  def definition(row, template)
84
79
  { label: label(row), properties: properties(row), name: row[:name],
85
- create_statement: row[:createStatement] || send(template,label(row), row[:properties]) }
80
+ create_statement: row[:createStatement] || send(template, label(row), row[:properties]) }
86
81
  end
87
82
 
88
83
  def label(row)
89
- row[version?('>=4') ? :labelsOrTypes : :tokenNames].first.to_sym
84
+ row[:labelsOrTypes].first.to_sym
90
85
  end
91
86
 
92
87
  def properties(row)
@@ -0,0 +1,13 @@
1
+ module ActiveGraph
2
+ module Core
3
+ class Type < Element
4
+ def pattern(spec)
5
+ "()-[#{spec}]-()"
6
+ end
7
+
8
+ def element_type
9
+ 'RELATIONSHIP'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -6,18 +6,16 @@ module ActiveGraph
6
6
  MISSING_CONSTRAINT_OR_INDEX = 'No such %{type} for %{label}#%{property}'.freeze
7
7
  DUPLICATE_CONSTRAINT_OR_INDEX = 'Duplicate %{type} for %{label}#%{property}'.freeze
8
8
 
9
- def add_constraint(label, property, options = {})
10
- force = options[:force] || false
11
- type = options[:type] || :uniqueness
12
- label_object = ActiveGraph::Base.label_object(label)
13
- if label_object.constraint?(property)
9
+ def add_constraint(name, property, relationship: false, type: :key, force: false)
10
+ element = ActiveGraph::Base.element(name, relationship:)
11
+ if element.constraint?(property)
14
12
  if force
15
- label_object.drop_constraint(property, type: type)
13
+ element.drop_constraint(property, type:)
16
14
  else
17
- fail_duplicate_constraint_or_index!(:constraint, label, property)
15
+ fail_duplicate_constraint_or_index!(:constraint, name, property)
18
16
  end
19
17
  end
20
- label_object.create_constraint(property, type: type)
18
+ element.create_constraint(property, type:)
21
19
  end
22
20
 
23
21
  def add_index(label, property, options = {})
@@ -33,11 +31,10 @@ module ActiveGraph
33
31
  label_object.create_index(property)
34
32
  end
35
33
 
36
- def drop_constraint(label, property, options = {})
37
- type = options[:type] || :uniqueness
38
- label_object = ActiveGraph::Base.label_object(label)
39
- fail_missing_constraint_or_index!(:constraint, label, property) if !options[:force] && !label_object.constraint?(property)
40
- label_object.drop_constraint(property, type: type)
34
+ def drop_constraint(name, property, type: :key, relationship: false, force: false)
35
+ element = ActiveGraph::Base.element(name, relationship:)
36
+ fail_missing_constraint_or_index!(:constraint, name, property) unless force || element.constraint?(property)
37
+ element.drop_constraint(property, type:)
41
38
  end
42
39
 
43
40
  def drop_index(label, property, options = {})
@@ -55,7 +55,7 @@ module ActiveGraph
55
55
  # should be private
56
56
  def schema_elements_list(by_model, db_results)
57
57
  by_model.flat_map do |model, property_names|
58
- label = model.mapped_label_name.to_sym
58
+ label = model.mapped_element_name.to_sym
59
59
  property_names.map do |property_name|
60
60
  exists = db_results[label] && db_results[label].include?([property_name])
61
61
  [model, label, property_name, exists]
@@ -111,13 +111,17 @@ module ActiveGraph::Node
111
111
 
112
112
  def add_to_cache(object, rel = nil)
113
113
  (@cached_rels ||= []) << rel if rel
114
- (@cached_result ||= []).tap { |results| results << object if object && !results.include?(object) }
114
+ (@cached_result ||= []).tap { |results| results << object if !results.include?(object) } if object
115
115
  end
116
116
 
117
117
  def rels
118
118
  @cached_rels || super.tap { |rels| rels.each { |rel| add_to_cache(nil, rel) } }
119
119
  end
120
120
 
121
+ def rel
122
+ rels.first
123
+ end
124
+
121
125
  def cache_query_proxy_result
122
126
  (result_cache_proc_cache || @query_proxy).to_a.tap { |result| cache_result(result) }
123
127
  end
@@ -282,7 +286,7 @@ module ActiveGraph::Node
282
286
  query_proxy = self.class.as(:previous).where(neo_id: result_cache.map(&:neo_id))
283
287
  query_proxy = self.class.send(:association_query_proxy, association_name, previous_query_proxy: query_proxy, node: :next, optional: true)
284
288
 
285
- Hash[*query_proxy.pluck('ID(previous)', 'collect(next)').flatten(1)].each_value do |records|
289
+ Hash[*query_proxy.pluck('elementId(previous)', 'collect(next)').flatten(1)].each_value do |records|
286
290
  records.each do |record|
287
291
  record.instance_variable_set('@source_proxy_result_cache', records)
288
292
  end