diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ece9538b0..a32922995 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,18 +5,16 @@ on: branches: [ '10' ] pull_request: branches: [ '10' ] - - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: - jobs: test: runs-on: ubuntu-18.04 + continue-on-error: ${{ matrix.neo4j > '4.0' }} strategy: fail-fast: false matrix: ruby: [ 2.5, 3.0, 3.1, jruby-9.3.3.0 ] - neo4j: [ 3.5.30, 4.0.12 ] + neo4j: [ 3.5.30, 4.0.12, 4.1.11, 4.2.15, 4.3.10, 4.4.4 ] driver: [ ffi ] include: - ruby: jruby-9.3.3.0 diff --git a/lib/active_graph/core/schema.rb b/lib/active_graph/core/schema.rb index 535efc033..5aae0270c 100644 --- a/lib/active_graph/core/schema.rb +++ b/lib/active_graph/core/schema.rb @@ -2,28 +2,32 @@ module ActiveGraph module Core module Schema def version - result = query('CALL dbms.components()', {}, skip_instrumentation: true) - # BTW: community / enterprise could be retrieved via `result.first.edition` - result.first[:versions][0] + query('CALL dbms.components()', {}, skip_instrumentation: true).first[:versions][0] end def indexes - result = query('CALL db.indexes()', {}, skip_instrumentation: true) - - result.map do |row| - { type: row[:type].to_sym, label: label(result, row), properties: properties(row), state: row[:state].to_sym } + raw_indexes do |keys, result| + result.map do |row| + { type: row[:type].to_sym, label: label(keys, row), properties: properties(row), + state: row[:state].to_sym } + end end end def constraints - result = query('CALL db.indexes()', {}, skip_instrumentation: true) - - result.select(&method(v4?(result) ? :v4_filter : :v3_filter)).map do |row| - { type: :uniqueness, label: label(result, row), properties: properties(row) } + raw_indexes do |keys, result| + result.select(&method(v4?(keys) ? :v4_filter : :v3_filter)).map do |row| + { type: :uniqueness, label: label(keys, row), properties: properties(row) } + end end end + def raw_indexes + result = query('CALL db.indexes()', {}, skip_instrumentation: true) + yield result.keys, result.reject { |row| row[:type] == 'LOOKUP' } + end + private def v4_filter(row) @@ -34,22 +38,22 @@ def v3_filter(row) row[:type] == 'node_unique_property' end - def label(result, row) - if v34?(result) + def label(keys, row) + if v34?(keys) row[:label] else - (v4?(result) ? row[:labelsOrTypes] : row[:tokenNames]).first + (v4?(keys) ? row[:labelsOrTypes] : row[:tokenNames]).first end.to_sym end - def v4?(result) + def v4?(keys) return @v4 unless @v4.nil? - @v4 = result.keys.include?(:labelsOrTypes) + @v4 = keys.include?(:labelsOrTypes) end - def v34?(result) + def v34?(keys) return @v34 unless @v34.nil? - @v34 = result.keys.include?(:label) + @v34 = keys.include?(:label) end def properties(row) diff --git a/lib/active_graph/migrations/base.rb b/lib/active_graph/migrations/base.rb index 97237d567..4867b8dfe 100644 --- a/lib/active_graph/migrations/base.rb +++ b/lib/active_graph/migrations/base.rb @@ -57,9 +57,13 @@ def run_migration(direction) end def handle_migration_error!(e) - fail e unless e.message =~ /Cannot perform data updates in a transaction that has performed schema updates./ - fail MigrationError, - "#{e.message}. Please add `disable_transactions!` in your migration file." + if e.is_a?(Neo4j::Driver::Exceptions::ClientException) && + e.code == 'Neo.ClientError.Transaction.ForbiddenDueToTransactionType' || + e.message =~ /Cannot perform data updates in a transaction that has performed schema updates./ + fail MigrationError, "#{e.message}. Please add `disable_transactions!` in your migration file." + else + fail e + end end def migration_transaction(&block) diff --git a/lib/active_graph/version.rb b/lib/active_graph/version.rb index fa467335b..794709dcc 100644 --- a/lib/active_graph/version.rb +++ b/lib/active_graph/version.rb @@ -1,3 +1,3 @@ module ActiveGraph - VERSION = '10.1.1' + VERSION = '10.2.0.beta.1' end diff --git a/spec/active_graph/base_spec.rb b/spec/active_graph/base_spec.rb index 4e1042011..e3c9e3e36 100644 --- a/spec/active_graph/base_spec.rb +++ b/spec/active_graph/base_spec.rb @@ -356,14 +356,14 @@ def create_index(label_name, property, options = {}) it 'raises an error' do expect do described_class.query("CRATE (:Album {uuid: 'dup'})").to_a - end.to raise_error(Neo4j::Driver::Exceptions::ClientException, /Invalid input 'A'/) + end.to raise_error(Neo4j::Driver::Exceptions::ClientException, /Invalid input '.*A.*'/) end end describe 'Clause ordering error' do it 'raises an error' do expect do - described_class.query("RETURN a CREATE (a:Album {uuid: 'dup'})").to_a + described_class.query("RETURN 1 CREATE (a:Album {uuid: 'dup'})").to_a end.to raise_error Neo4j::Driver::Exceptions::ClientException, /RETURN can only be used at the end of the query/ end end diff --git a/spec/e2e/id_property_spec.rb b/spec/e2e/id_property_spec.rb index 1a55ba0b0..80149da8a 100644 --- a/spec/e2e/id_property_spec.rb +++ b/spec/e2e/id_property_spec.rb @@ -195,7 +195,7 @@ end - EXISTS_REGEXP = /Node.\d+\)? already exists with label/ + EXISTS_REGEXP = /Node.\d+\)? already exists with label|New data does not satisfy Constraint/ describe 'id_property :my_id, on: :foobar' do before do diff --git a/spec/unit/shared/attributes_spec.rb b/spec/unit/shared/attributes_spec.rb index 3e2f2285f..aaa4d2df2 100644 --- a/spec/unit/shared/attributes_spec.rb +++ b/spec/unit/shared/attributes_spec.rb @@ -222,7 +222,7 @@ def self.name it 'raises when setting an undefined attribute' do expect do model.send(method, :initials, 'BP') - end.to raise_error ActiveGraph::UnknownAttributeError, 'unknown attribute: initials' + end.to raise_error ActiveGraph::UnknownAttributeError, /unknown attribute: initials/ end end end