activegraph 11.1.0.beta.1 → 11.1.0

Sign up to get free protection for your applications and to get access to all the features.
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