activegraph 11.1.0 → 11.2.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: f665b5c84fb15ec151bae2809606a3ab2ad9a5f521938c8b84c61499fdb1d24a
4
- data.tar.gz: 5fae844b9ce18bee486e2b71c9aa370dff52f703608251c9927bfc4f53e84487
3
+ metadata.gz: 4b0ec846225c753d7a2dc2bc3923c95f52dec582324559df182f23df633f564c
4
+ data.tar.gz: 1205c8eaf374112629a173f55e2c9a5fae42324073b2f540815eb984cb87e324
5
5
  SHA512:
6
- metadata.gz: c127dfaabbd5e864f12f15b869baf5e609953e66550e7c0c40b8ad28fb16663cf865d6189ff1f6cd0b1a8f98e570033ab624b24ca4d59d7b9322bb568ddafd3a
7
- data.tar.gz: 31f99b876df02ccf43cd51c0794725df354883122a131cd14cf9c569b74a3daa01e0db5179e963e440d8bab164095a81b25b80ac627c41e52e7a51d128110562
6
+ metadata.gz: '07091d4bf26b0b2bfb4d6313668e358eb78f8eb6afb7244063a2293a3596963687debf7fe6e72177ba388ac008a9452a8bd580fb48064575354e0e208765f475'
7
+ data.tar.gz: '09dc2f6eaf0126d26b76aba057b9b7e77e0b633f0b13ab99964ed64fd64e7421f22eaa470d9abd0fca4bd896e122ca938814683bc0c618e7d37d2ded400c00de'
data/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@ 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.2.0] 2023-02-06
7
+
8
+ ## Added
9
+
10
+ - support for neo4j:schema:dump and :load for neo4j 4 and 5. No automatic migration of schema on major neo4j upgrades. Schema must be regenerated with neo4j:schema:dump or manually adjusted to new syntax on those upgrades.
11
+
6
12
  ## [11.1.0] 2023-01-10
7
13
 
8
14
  ## Added
@@ -19,17 +19,22 @@ module ActiveGraph
19
19
  end
20
20
 
21
21
  def indexes
22
- raw_indexes.map do |row|
23
- definition(row).merge(type: row[:type].to_sym, state: row[:state].to_sym)
22
+ normalize(raw_indexes, *%i[type state])
23
+ end
24
+
25
+ def normalize(result, *extra)
26
+ 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] })
24
29
  end
25
30
  end
26
31
 
27
32
  def constraints
28
33
  if version?('<4.3')
29
- raw_indexes.select(&method(:filter))
34
+ raw_indexes.select(&method(:constraint_owned?))
30
35
  else
31
36
  raw_constraints.select(&method(:constraint_filter))
32
- end.map { |row| definition(row).merge(type: :uniqueness) }
37
+ end.map { |row| definition(row, :constraint_cypher).merge(type: :uniqueness) }
33
38
  end
34
39
 
35
40
  private def raw_constraints
@@ -45,22 +50,39 @@ module ActiveGraph
45
50
  end
46
51
  end
47
52
 
53
+ def constraint_owned?(record)
54
+ FILTER[major]&.then { |(key, value)| record[key] == value } || record[:owningConstraint]
55
+ end
56
+
48
57
  private
49
58
 
50
59
  def major
51
60
  @major ||= version.segments.first
52
61
  end
53
62
 
54
- def filter(record)
55
- FILTER[major].then { |(key, value)| record[key] == value }
63
+ def constraint_filter(record)
64
+ %w[UNIQUENESS RELATIONSHIP_PROPERTY_EXISTENCE NODE_PROPERTY_EXISTENCE NODE_KEY].include?(record[:type])
56
65
  end
57
66
 
58
- def constraint_filter(record)
59
- record[:type] == 'UNIQUENESS'
67
+ def index_cypher_v3(label, properties)
68
+ "INDEX ON :#{label}#{com_sep(properties, nil)}"
69
+ end
70
+
71
+ def index_cypher(label, properties)
72
+ "INDEX FOR (n:#{label}) ON #{com_sep(properties)}"
73
+ end
74
+
75
+ def constraint_cypher(label, properties)
76
+ "CONSTRAINT ON (n:#{label}) ASSERT #{com_sep(properties)} IS UNIQUE"
77
+ end
78
+
79
+ def com_sep(properties, prefix = 'n.')
80
+ "(#{properties.map { |prop| "#{prefix}#{prop}" }.join(', ')})"
60
81
  end
61
82
 
62
- def definition(row)
63
- { label: label(row), properties: properties(row), name: row[:name] }
83
+ def definition(row, template)
84
+ { label: label(row), properties: properties(row), name: row[:name],
85
+ create_statement: row[:createStatement] || send(template,label(row), row[:properties]) }
64
86
  end
65
87
 
66
88
  def label(row)
@@ -5,7 +5,7 @@ require 'active_graph/core/query'
5
5
  require 'active_graph/core/record'
6
6
  require 'active_graph/core/wrappable'
7
7
  require 'active_graph/transaction'
8
- require 'neo4j_ruby_driver'
8
+ require 'neo4j/driver'
9
9
 
10
10
  Neo4j::Driver::Types::Entity.include ActiveGraph::Core::Wrappable
11
11
  Neo4j::Driver::Types::Entity.prepend ActiveGraph::Core::Entity
@@ -3,15 +3,15 @@ module ActiveGraph
3
3
  module Schema
4
4
  class << self
5
5
  def fetch_schema_data
6
- { constraints: fetch_constraint_descriptions.sort, indexes: fetch_index_descriptions.sort }
6
+ %i[constraints indexes].to_h { |schema_elem| [schema_elem, send("fetch_#{schema_elem}_descriptions").keys] }
7
7
  end
8
8
 
9
9
  def synchronize_schema_data(schema_data, remove_missing)
10
- queries = []
11
- ActiveGraph::Base.read_transaction do
12
- queries += drop_and_create_queries(fetch_constraint_descriptions, schema_data[:constraints], remove_missing)
13
- queries += drop_and_create_queries(fetch_index_descriptions, schema_data[:indexes], remove_missing)
14
- end
10
+ queries =
11
+ ActiveGraph::Base.read_transaction do
12
+ drop_and_create_queries(fetch_constraints_descriptions, schema_data[:constraints], 'CONSTRAINT', remove_missing) +
13
+ drop_and_create_queries(fetch_indexes_descriptions, schema_data[:indexes], 'INDEX', remove_missing)
14
+ end
15
15
  ActiveGraph::Base.write_transaction do
16
16
  queries.each(&ActiveGraph::Base.method(:query))
17
17
  end
@@ -19,46 +19,30 @@ module ActiveGraph
19
19
 
20
20
  private
21
21
 
22
- def fetch_constraint_descriptions
23
- ActiveGraph::Base.query('CALL db.constraints() YIELD description').map(&:first)
22
+ def fetch_indexes_descriptions
23
+ ActiveGraph::Base.raw_indexes.reject(&ActiveGraph::Base.method(:constraint_owned?))
24
+ .then(&ActiveGraph::Base.method(:normalize)).then(&method(:fetch_descriptions))
24
25
  end
25
26
 
26
- def fetch_index_descriptions
27
- ActiveGraph::Base.raw_indexes do |keys, result|
28
- if keys.include?(:description)
29
- v3_indexes(result)
30
- else
31
- v4_indexes(result)
32
- end
33
- end
27
+ def fetch_constraints_descriptions
28
+ fetch_descriptions(ActiveGraph::Base.constraints)
34
29
  end
35
30
 
36
- def v3_indexes(result)
37
- result.reject do |row|
38
- # These indexes are created automagically when the corresponding constraints are created
39
- row[:type] == 'node_unique_property'
40
- end.map { |row| row[:description] }
31
+ def fetch_descriptions(results)
32
+ results.map { |definition| definition.values_at(:create_statement, :name) }.sort.to_h
41
33
  end
42
34
 
43
- def v4_indexes(result)
44
- result.reject do |row|
45
- # These indexes are created automagically when the corresponding constraints are created
46
- row[:uniqueness] == 'UNIQUE'
47
- end.map(&method(:description))
35
+ def drop_and_create_queries(existing, specified, schema_elem, remove_missing)
36
+ (remove_missing ? existing.except(*specified).map { |stmt, name| drop_statement(schema_elem, stmt, name) } : []) +
37
+ (specified - existing.keys).map(&method(:create_statement))
48
38
  end
49
39
 
50
- def description(row)
51
- "INDEX FOR (n:#{row[:labelsOrTypes].first}) ON (#{row[:properties].map { |prop| "n.#{prop}" }.join(', ')})"
40
+ def drop_statement(schema_elem, create_statement, name)
41
+ "DROP #{name&.then { |name| "#{schema_elem} #{name}" } || create_statement}"
52
42
  end
53
43
 
54
- def drop_and_create_queries(existing, specified, remove_missing)
55
- [].tap do |queries|
56
- if remove_missing
57
- (existing - specified).each { |description| queries << "DROP #{description}" }
58
- end
59
-
60
- (specified - existing).each { |description| queries << "CREATE #{description}" }
61
- end
44
+ def create_statement(stmt)
45
+ stmt.start_with?('CREATE ') ? stmt : "CREATE #{stmt}"
62
46
  end
63
47
  end
64
48
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveGraph
2
- VERSION = '11.1.0'
2
+ VERSION = '11.2.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
4
+ version: 11.2.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: 2023-01-11 00:00:00.000000000 Z
11
+ date: 2023-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -444,7 +444,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
444
444
  - !ruby/object:Gem::Version
445
445
  version: '0'
446
446
  requirements: []
447
- rubygems_version: 3.3.26
447
+ rubygems_version: 3.4.1
448
448
  signing_key:
449
449
  specification_version: 4
450
450
  summary: A graph database for Ruby