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 +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +16 -15
- data/activegraph.gemspec +1 -1
- data/lib/active_graph/core/label.rb +56 -18
- data/lib/active_graph/core/schema.rb +35 -28
- data/lib/active_graph/migrations/helpers/id_property.rb +2 -2
- data/lib/active_graph/migrations/helpers.rb +1 -1
- data/lib/active_graph/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f665b5c84fb15ec151bae2809606a3ab2ad9a5f521938c8b84c61499fdb1d24a
|
4
|
+
data.tar.gz: 5fae844b9ce18bee486e2b71c9aa370dff52f703608251c9927bfc4f53e84487
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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.
|
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(
|
11
|
+
def create_index(*properties, **options)
|
11
12
|
validate_index_options!(options)
|
12
|
-
|
13
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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(
|
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
|
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 |
|
13
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
31
|
-
|
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
|
38
|
-
|
50
|
+
def major
|
51
|
+
@major ||= version.segments.first
|
39
52
|
end
|
40
53
|
|
41
|
-
def
|
42
|
-
|
54
|
+
def filter(record)
|
55
|
+
FILTER[major].then { |(key, value)| record[key] == value }
|
43
56
|
end
|
44
57
|
|
45
|
-
def
|
46
|
-
|
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
|
54
|
-
|
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
|
59
|
-
|
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("
|
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
|
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]]|
|
data/lib/active_graph/version.rb
CHANGED
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
|
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:
|
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.
|
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.
|
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:
|
445
|
+
version: '0'
|
446
446
|
requirements: []
|
447
|
-
rubygems_version: 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
|