activegraph 11.5.0.alpha.1 → 12.0.0.beta.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.
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