activegraph 11.1.0.beta.1 → 11.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4aade7db7557b1222b78e048550606354b0707a60c9375359a4f945b702763c2
4
- data.tar.gz: a22b396cdc491118ecbaf947ac9e00d9ea088fe0df5afa51a3a38b7f085db9ff
3
+ metadata.gz: f665b5c84fb15ec151bae2809606a3ab2ad9a5f521938c8b84c61499fdb1d24a
4
+ data.tar.gz: 5fae844b9ce18bee486e2b71c9aa370dff52f703608251c9927bfc4f53e84487
5
5
  SHA512:
6
- metadata.gz: 663bc1323338cc7261cb2281b5ad6a86d794baed1fd2dc82a08f8d1b5eae593a151927529330425d8ffdc71adb17e8a7c70aa3872c63641cd2d77dcfe46016cc
7
- data.tar.gz: c894eff95679b5982e418dccff5deb160ff41a46e661bee2f8278b230ab59fe20befc8aed83b8144dd112485df98d61c6fa1f60d226f63a1df3db6cd34b4a9a4
6
+ metadata.gz: c127dfaabbd5e864f12f15b869baf5e609953e66550e7c0c40b8ad28fb16663cf865d6189ff1f6cd0b1a8f98e570033ab624b24ca4d59d7b9322bb568ddafd3a
7
+ data.tar.gz: 31f99b876df02ccf43cd51c0794725df354883122a131cd14cf9c569b74a3daa01e0db5179e963e440d8bab164095a81b25b80ac627c41e52e7a51d128110562
data/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@ 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.1.0] 2023-01-10
7
+
8
+ ## Added
9
+
10
+ - support for pure ruby driver, neo4j-ruby-driver 4.4
11
+ - support for neo4j 5
12
+
13
+ ## Fixed
14
+
15
+ - moved migrations into their own transactions
16
+ - Uniqueness within a scope defined by a proc
17
+ - Fixed lost @rel_var when branching QueryProxy
18
+
6
19
  ## [11.0.2] 2021-11-05
7
20
 
8
21
  ## Fixed
data/README.md CHANGED
@@ -45,21 +45,22 @@ Neo4j.rb v4.1.0 was released in January of 2015. Its changes are outlined [here]
45
45
 
46
46
  ## Neo4j version support
47
47
 
48
- | **Neo4j Version** | v2.x | v3.x | >= v4.x | >= 7.0.3 | activegraph 10 | activegraph 11 (jRuby only) |
49
- |-------------------|------|-------|---------|----------|------------------|-----------------------------|
50
- | 1.9.x | Yes | No | No | No | No | No
51
- | 2.0.x | No | Yes | No | No | No | No
52
- | 2.1.x | No | Yes | Yes * | Yes | No | No
53
- | 2.2.x | No | No | Yes | Yes | No | No
54
- | 2.3.x | No | No | Yes | Yes | No | No
55
- | 3.0, 3.1, 3.3 | No | No | No | Yes | No | No
56
- | 3.4 | No | No | No | Yes | Yes | No
57
- | 3.5 | No | No | No | Yes | Yes | Yes
58
- | 4.0 | No | No | No | No | Yes | Yes
59
- | 4.1 | No | No | No | No | No | Yes
60
- | 4.2 | No | No | No | No | No | Yes
61
- | 4.3 | No | No | No | No | No | Yes
62
- | 4.4 | No | No | No | No | No | Yes
48
+ | **Neo4j Version** | v2.x | v3.x | >= v4.x | >= 7.0.3 | activegraph 10 | activegraph 11.1 |
49
+ |-------------------|------|-------|---------|----------|------------------|------------------|
50
+ | 1.9.x | Yes | No | No | No | No | No
51
+ | 2.0.x | No | Yes | No | No | No | No
52
+ | 2.1.x | No | Yes | Yes * | Yes | No | No
53
+ | 2.2.x | No | No | Yes | Yes | No | No
54
+ | 2.3.x | No | No | Yes | Yes | No | No
55
+ | 3.0, 3.1, 3.3 | No | No | No | Yes | No | No
56
+ | 3.4 | No | No | No | Yes | Yes | No
57
+ | 3.5 | No | No | No | Yes | Yes | Yes
58
+ | 4.0 | No | No | No | No | Yes | Yes
59
+ | 4.1 | No | No | No | No | No | Yes
60
+ | 4.2 | No | No | No | No | No | Yes
61
+ | 4.3 | No | No | No | No | No | Yes
62
+ | 4.4 | No | No | No | No | No | Yes
63
+ | 5.x | No | No | No | No | No | Yes
63
64
 
64
65
  `*` Neo4j.rb >= 4.x doesn't support Neo4j versions before 2.1.5. To use 2.1.x you should upgrade to a version >= 2.1.5
65
66
 
data/activegraph.gemspec CHANGED
@@ -33,7 +33,7 @@ DESCRIPTION
33
33
  s.add_dependency('activemodel', '>= 4.0')
34
34
  s.add_dependency('activesupport', '>= 4.0')
35
35
  s.add_dependency('i18n', '!= 1.8.8') # https://github.com/jruby/jruby/issues/6547
36
- s.add_dependency('neo4j-ruby-driver', '>= 4.4.0.alpha.7')
36
+ s.add_dependency('neo4j-ruby-driver', '>= 4.4.1')
37
37
  s.add_dependency('orm_adapter', '~> 0.5.0')
38
38
  s.add_dependency('sorted_set')
39
39
  s.add_development_dependency('guard')
@@ -2,20 +2,33 @@ module ActiveGraph
2
2
  module Core
3
3
  class Label
4
4
  attr_reader :name
5
+ delegate :version?, to: ActiveGraph::Base
5
6
 
6
7
  def initialize(name)
7
8
  @name = name
8
9
  end
9
10
 
10
- def create_index(property, options = {})
11
+ def create_index(*properties, **options)
11
12
  validate_index_options!(options)
12
- properties = property.is_a?(Array) ? property.join(',') : property
13
- schema_query("CREATE INDEX ON :`#{@name}`(#{properties})")
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('.')})")
14
20
  end
15
21
 
16
22
  def drop_index(property, options = {})
17
23
  validate_index_options!(options)
18
- schema_query("DROP INDEX ON :`#{@name}`(#{property})")
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
19
32
  end
20
33
 
21
34
  # Creates a neo4j constraint on a property
@@ -27,7 +40,8 @@ module ActiveGraph
27
40
  def create_constraint(property, constraints)
28
41
  cypher = case constraints[:type]
29
42
  when :unique, :uniqueness
30
- "CREATE CONSTRAINT ON (n:`#{name}`) ASSERT n.`#{property}` IS UNIQUE"
43
+ _for, _require = version?('>=4.4') ? %w[FOR REQUIRE] : %w[ON ASSERT]
44
+ "CREATE CONSTRAINT #{_for} (n:`#{name}`) #{_require} n.`#{property}` IS UNIQUE"
31
45
  else
32
46
  fail "Not supported constraint #{constraints.inspect} for property #{property} (expected :type => :unique)"
33
47
  end
@@ -46,15 +60,20 @@ module ActiveGraph
46
60
  # label.drop_constraint(:name, {type: :unique})
47
61
  #
48
62
  def drop_constraint(property, constraint)
49
- cypher = case constraint[:type]
50
- when :unique, :uniqueness
51
- "n.`#{property}` IS UNIQUE"
52
- when :exists
53
- "exists(n.`#{property}`)"
54
- else
55
- fail "Not supported constraint #{constraint.inspect}"
56
- end
57
- schema_query("DROP CONSTRAINT ON (n:`#{name}`) ASSERT #{cypher}")
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
58
77
  end
59
78
 
60
79
  def drop_uniqueness_constraint(property, options = {})
@@ -105,7 +124,12 @@ module ActiveGraph
105
124
  def drop_indexes
106
125
  indexes.each do |definition|
107
126
  begin
108
- ActiveGraph::Base.query("DROP INDEX ON :`#{definition[:label]}`(#{definition[:properties][0]})")
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)
109
133
  rescue Neo4j::Driver::Exceptions::DatabaseException
110
134
  # This will error on each constraint. Ignore and continue.
111
135
  next
@@ -114,7 +138,9 @@ module ActiveGraph
114
138
  end
115
139
 
116
140
  def drop_constraints
117
- result = ActiveGraph::Base.read_transaction { |tx| tx.run('CALL db.constraints').to_a }
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
118
144
  ActiveGraph::Base.write_transaction do |tx|
119
145
  result.each do |record|
120
146
  tx.run("DROP #{record.keys.include?(:name) ? "CONSTRAINT #{record[:name]}" : record[:description]}")
@@ -123,14 +149,26 @@ module ActiveGraph
123
149
  end
124
150
  end
125
151
 
126
- def schema_query(cypher)
127
- ActiveGraph::Base.query(cypher, {})
152
+ def schema_query(cypher, **params)
153
+ ActiveGraph::Base.query(cypher, params)
128
154
  end
129
155
 
130
156
  def validate_index_options!(options)
131
157
  return unless options[:type] && options[:type] != :exact
132
158
  fail "Type #{options[:type]} is not supported"
133
159
  end
160
+
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}")
171
+ end
134
172
  end
135
173
  end
136
174
  end
@@ -1,63 +1,70 @@
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
+
4
9
  def version
5
- read_transaction do
10
+ @version ||= read_transaction do
6
11
  # BTW: community / enterprise could be retrieved via `result.first.edition`
7
12
  query('CALL dbms.components()', {}, skip_instrumentation: true).first[:versions][0]
13
+ .then(&Gem::Version.method(:new))
8
14
  end
9
15
  end
10
16
 
17
+ def version?(requirement)
18
+ Gem::Requirement.create(requirement).satisfied_by?(Gem::Version.new(version))
19
+ end
20
+
11
21
  def indexes
12
- raw_indexes do |keys, result|
13
- result.map do |row|
14
- { type: row[:type].to_sym, label: label(keys, row), properties: properties(row),
15
- state: row[:state].to_sym }
16
- end
22
+ raw_indexes.map do |row|
23
+ definition(row).merge(type: row[:type].to_sym, state: row[:state].to_sym)
17
24
  end
18
25
  end
19
26
 
20
27
  def constraints
21
- raw_indexes do |keys, result|
22
- result.select(&method(v4?(keys) ? :v4_filter : :v3_filter)).map do |row|
23
- { type: :uniqueness, label: label(keys, row), properties: properties(row) }
24
- end
28
+ if version?('<4.3')
29
+ raw_indexes.select(&method(:filter))
30
+ else
31
+ raw_constraints.select(&method(:constraint_filter))
32
+ end.map { |row| definition(row).merge(type: :uniqueness) }
33
+ end
34
+
35
+ private def raw_constraints
36
+ read_transaction do
37
+ query('SHOW CONSTRAINTS YIELD *', {}, skip_instrumentation: true).to_a
25
38
  end
26
39
  end
27
40
 
28
41
  def raw_indexes
29
42
  read_transaction do
30
- result = query('CALL db.indexes()', {}, skip_instrumentation: true)
31
- yield result.keys, result.reject { |row| row[:type] == 'LOOKUP' }
43
+ query(version?('<4.3') ? 'CALL db.indexes()' : 'SHOW INDEXES YIELD *', {}, skip_instrumentation: true)
44
+ .reject { |row| row[:type] == 'LOOKUP' }
32
45
  end
33
46
  end
34
47
 
35
48
  private
36
49
 
37
- def v4_filter(row)
38
- row[:uniqueness] == 'UNIQUE'
50
+ def major
51
+ @major ||= version.segments.first
39
52
  end
40
53
 
41
- def v3_filter(row)
42
- row[:type] == 'node_unique_property'
54
+ def filter(record)
55
+ FILTER[major].then { |(key, value)| record[key] == value }
43
56
  end
44
57
 
45
- def label(keys, row)
46
- if v34?(keys)
47
- row[:label]
48
- else
49
- (v4?(keys) ? row[:labelsOrTypes] : row[:tokenNames]).first
50
- end.to_sym
58
+ def constraint_filter(record)
59
+ record[:type] == 'UNIQUENESS'
51
60
  end
52
61
 
53
- def v4?(keys)
54
- return @v4 unless @v4.nil?
55
- @v4 = keys.include?(:labelsOrTypes)
62
+ def definition(row)
63
+ { label: label(row), properties: properties(row), name: row[:name] }
56
64
  end
57
65
 
58
- def v34?(keys)
59
- return @v34 unless @v34.nil?
60
- @v34 = keys.include?(:label)
66
+ def label(row)
67
+ row[version?('>=4') ? :labelsOrTypes : :tokenNames].first.to_sym
61
68
  end
62
69
 
63
70
  def properties(row)
@@ -23,12 +23,12 @@ module ActiveGraph
23
23
  protected
24
24
 
25
25
  def idless_count(label, id_property)
26
- query.match(n: label).where("NOT EXISTS(n.#{id_property})").pluck('COUNT(n) AS ids').first
26
+ query.match(n: label).where("n.#{id_property} IS NULL").pluck('COUNT(n) AS ids').first
27
27
  end
28
28
 
29
29
  def id_batch_set(label, id_property, new_ids, count)
30
30
  ActiveGraph::Base.transaction do
31
- execute("MATCH (n:`#{label}`) WHERE NOT EXISTS(n.#{id_property})
31
+ execute("MATCH (n:`#{label}`) WHERE n.#{id_property} IS NULL
32
32
  with COLLECT(n) as nodes, #{new_ids} as ids
33
33
  FOREACH(i in range(0,#{count - 1})|
34
34
  FOREACH(node in [nodes[i]]|
@@ -83,7 +83,7 @@ module ActiveGraph
83
83
  private
84
84
 
85
85
  def property_exists?(label, property)
86
- by_label(label).where("EXISTS(n.#{property})").return(:n).any?
86
+ by_label(label).where("n.#{property} IS NOT NULL").return(:n).any?
87
87
  end
88
88
 
89
89
  def by_label(label, options = {})
@@ -1,3 +1,3 @@
1
1
  module ActiveGraph
2
- VERSION = '11.1.0.beta.1'
2
+ VERSION = '11.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activegraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.1.0.beta.1
4
+ version: 11.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Ronge, Brian Underwood, Chris Grigg, Heinrich Klobuczek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-23 00:00:00.000000000 Z
11
+ date: 2023-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 4.4.0.alpha.7
61
+ version: 4.4.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 4.4.0.alpha.7
68
+ version: 4.4.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: orm_adapter
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -440,11 +440,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
440
440
  version: '2.6'
441
441
  required_rubygems_version: !ruby/object:Gem::Requirement
442
442
  requirements:
443
- - - ">"
443
+ - - ">="
444
444
  - !ruby/object:Gem::Version
445
- version: 1.3.1
445
+ version: '0'
446
446
  requirements: []
447
- rubygems_version: 3.3.3
447
+ rubygems_version: 3.3.26
448
448
  signing_key:
449
449
  specification_version: 4
450
450
  summary: A graph database for Ruby