neospace 0.0.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +88 -0
- data/ffi/bolt/address.rb +11 -0
- data/ffi/bolt/address_resolver.rb +12 -0
- data/ffi/bolt/address_set.rb +9 -0
- data/ffi/bolt/auth.rb +10 -0
- data/ffi/bolt/auto_releasable.rb +22 -0
- data/ffi/bolt/boolean.rb +9 -0
- data/ffi/bolt/bytes.rb +10 -0
- data/ffi/bolt/config.rb +45 -0
- data/ffi/bolt/connection.rb +44 -0
- data/ffi/bolt/connector.rb +17 -0
- data/ffi/bolt/dictionary.rb +15 -0
- data/ffi/bolt/error.rb +74 -0
- data/ffi/bolt/float.rb +9 -0
- data/ffi/bolt/integer.rb +9 -0
- data/ffi/bolt/library.rb +12 -0
- data/ffi/bolt/lifecycle.rb +9 -0
- data/ffi/bolt/list.rb +10 -0
- data/ffi/bolt/log.rb +16 -0
- data/ffi/bolt/socket_options.rb +14 -0
- data/ffi/bolt/status.rb +25 -0
- data/ffi/bolt/string.rb +9 -0
- data/ffi/bolt/structure.rb +10 -0
- data/ffi/bolt/value.rb +35 -0
- data/ffi/neo4j/driver.rb +60 -0
- data/ffi/neo4j/driver/access_mode.rb +10 -0
- data/ffi/neo4j/driver/auth_tokens.rb +18 -0
- data/ffi/neo4j/driver/config.rb +40 -0
- data/ffi/neo4j/driver/graph_database.rb +52 -0
- data/ffi/neo4j/driver/internal/async/access_mode_connection.rb +19 -0
- data/ffi/neo4j/driver/internal/async/direct_connection.rb +106 -0
- data/ffi/neo4j/driver/internal/bolt_server_address.rb +18 -0
- data/ffi/neo4j/driver/internal/bookmarks_holder.rb +30 -0
- data/ffi/neo4j/driver/internal/direct_connection_provider.rb +28 -0
- data/ffi/neo4j/driver/internal/driver_factory.rb +125 -0
- data/ffi/neo4j/driver/internal/error_handling.rb +108 -0
- data/ffi/neo4j/driver/internal/explicit_transaction.rb +146 -0
- data/ffi/neo4j/driver/internal/handlers/pull_all_response_handler.rb +105 -0
- data/ffi/neo4j/driver/internal/handlers/response_handler.rb +49 -0
- data/ffi/neo4j/driver/internal/handlers/run_response_handler.rb +32 -0
- data/ffi/neo4j/driver/internal/handlers/session_pull_all_response_handler.rb +32 -0
- data/ffi/neo4j/driver/internal/handlers/transaction_pull_all_response_handler.rb +23 -0
- data/ffi/neo4j/driver/internal/internal_driver.rb +45 -0
- data/ffi/neo4j/driver/internal/internal_logger.rb +32 -0
- data/ffi/neo4j/driver/internal/internal_record.rb +26 -0
- data/ffi/neo4j/driver/internal/internal_resolver.rb +31 -0
- data/ffi/neo4j/driver/internal/internal_statement_result.rb +52 -0
- data/ffi/neo4j/driver/internal/messaging/bolt_protocol.rb +24 -0
- data/ffi/neo4j/driver/internal/messaging/v1/bolt_protocol_v1.rb +59 -0
- data/ffi/neo4j/driver/internal/messaging/v2/bolt_protocol_v2.rb +16 -0
- data/ffi/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +63 -0
- data/ffi/neo4j/driver/internal/network_session.rb +129 -0
- data/ffi/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +80 -0
- data/ffi/neo4j/driver/internal/session_factory_impl.rb +28 -0
- data/ffi/neo4j/driver/internal/summary/internal_result_summary.rb +67 -0
- data/ffi/neo4j/driver/internal/summary/internal_server_info.rb +19 -0
- data/ffi/neo4j/driver/internal/summary/internal_summary_counters.rb +23 -0
- data/ffi/neo4j/driver/internal/util/metadata_extractor.rb +15 -0
- data/ffi/neo4j/driver/internal/value/base_time_value.rb +22 -0
- data/ffi/neo4j/driver/internal/value/date_value.rb +25 -0
- data/ffi/neo4j/driver/internal/value/duration_value.rb +27 -0
- data/ffi/neo4j/driver/internal/value/local_date_time_value.rb +24 -0
- data/ffi/neo4j/driver/internal/value/local_time_value.rb +19 -0
- data/ffi/neo4j/driver/internal/value/node_value.rb +18 -0
- data/ffi/neo4j/driver/internal/value/offset_time_value.rb +25 -0
- data/ffi/neo4j/driver/internal/value/path_value.rb +41 -0
- data/ffi/neo4j/driver/internal/value/point2_d_value.rb +24 -0
- data/ffi/neo4j/driver/internal/value/point3_d_value.rb +24 -0
- data/ffi/neo4j/driver/internal/value/relationship_value.rb +18 -0
- data/ffi/neo4j/driver/internal/value/structure_value.rb +42 -0
- data/ffi/neo4j/driver/internal/value/time_with_zone_id_value.rb +25 -0
- data/ffi/neo4j/driver/internal/value/time_with_zone_offset_value.rb +28 -0
- data/ffi/neo4j/driver/internal/value/unbound_relationship_value.rb +18 -0
- data/ffi/neo4j/driver/internal/value/value_adapter.rb +99 -0
- data/ffi/neo4j/driver/net/server_address.rb +13 -0
- data/ffi/neo4j/driver/statement.rb +15 -0
- data/ffi/neo4j/driver/summary/statement_type.rb +14 -0
- data/ffi/neo4j/driver/types/entity.rb +21 -0
- data/ffi/neo4j/driver/types/node.rb +16 -0
- data/ffi/neo4j/driver/types/path.rb +35 -0
- data/ffi/neo4j/driver/types/relationship.rb +19 -0
- data/lib/loader.rb +18 -0
- data/lib/neo4j/driver/auto_closable.rb +32 -0
- data/lib/neo4j/driver/exceptions/authentication_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/client_exception.rb +15 -0
- data/lib/neo4j/driver/exceptions/database_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/illegal_state_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/neo4j_exception.rb +23 -0
- data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +33 -0
- data/lib/neo4j/driver/exceptions/protocol_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/security_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/service_unavailable_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/session_expired_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/transient_exception.rb +10 -0
- data/lib/neo4j/driver/exceptions/untrusted_server_exception.rb +10 -0
- data/lib/neo4j/driver/internal/duration_normalizer.rb +46 -0
- data/lib/neo4j/driver/internal/ruby_signature.rb +18 -0
- data/lib/neo4j/driver/internal/validator.rb +28 -0
- data/lib/neo4j/driver/types/bytes.rb +10 -0
- data/lib/neo4j/driver/types/local_date_time.rb +20 -0
- data/lib/neo4j/driver/types/local_time.rb +19 -0
- data/lib/neo4j/driver/types/offset_time.rb +19 -0
- data/lib/neo4j/driver/types/point.rb +39 -0
- data/lib/neo4j/driver/types/time.rb +43 -0
- data/lib/neo4j/driver/version.rb +7 -0
- data/lib/neo4j_ruby_driver.rb +20 -0
- metadata +314 -12
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Internal
|
6
|
+
module Value
|
7
|
+
module UnboundRelationshipValue
|
8
|
+
CODE = :r
|
9
|
+
extend StructureValue
|
10
|
+
|
11
|
+
def self.to_ruby_value(id, type, properties)
|
12
|
+
Types::Relationship.new(id, nil, nil, type, properties)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Internal
|
6
|
+
module Value
|
7
|
+
module ValueAdapter
|
8
|
+
class << self
|
9
|
+
def to_ruby(value)
|
10
|
+
case Bolt::Value.type(value)
|
11
|
+
when :bolt_null
|
12
|
+
nil
|
13
|
+
when :bolt_boolean
|
14
|
+
Bolt::Boolean.get(value) == 1
|
15
|
+
when :bolt_integer
|
16
|
+
Bolt::Integer.get(value)
|
17
|
+
when :bolt_float
|
18
|
+
Bolt::Float.get(value)
|
19
|
+
when :bolt_bytes
|
20
|
+
Types::Bytes.new(Array.new(Bolt::Value.size(value)) { |i| Bolt::Bytes.get(value, i) }.pack('C*'))
|
21
|
+
when :bolt_string
|
22
|
+
Bolt::String.get(value).read_string(Bolt::Value.size(value)).force_encoding(Encoding::UTF_8)
|
23
|
+
when :bolt_dictionary
|
24
|
+
Array.new(Bolt::Value.size(value)) do |i|
|
25
|
+
[to_ruby(Bolt::Dictionary.key(value, i)).to_sym, to_ruby(Bolt::Dictionary.value(value, i))]
|
26
|
+
end.to_h
|
27
|
+
when :bolt_list
|
28
|
+
Array.new(Bolt::Value.size(value)) { |i| to_ruby(Bolt::List.value(value, i)) }
|
29
|
+
when :bolt_structure
|
30
|
+
StructureValue.to_ruby(value)
|
31
|
+
else
|
32
|
+
raise Exception, 'unsupported neo4j type'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_neo(value, object)
|
37
|
+
case object
|
38
|
+
when nil
|
39
|
+
Bolt::Value.format_as_null(value)
|
40
|
+
when TrueClass
|
41
|
+
Bolt::Value.format_as_boolean(value, 1)
|
42
|
+
when FalseClass
|
43
|
+
Bolt::Value.format_as_boolean(value, 0)
|
44
|
+
when Integer
|
45
|
+
Bolt::Value.format_as_integer(value, object)
|
46
|
+
when Float
|
47
|
+
Bolt::Value.format_as_float(value, object)
|
48
|
+
when Types::Bytes
|
49
|
+
Bolt::Value.format_as_bytes(value, object, object.size)
|
50
|
+
when String
|
51
|
+
object = object.encode(Encoding::UTF_8) unless object.encoding == Encoding::UTF_8
|
52
|
+
Bolt::Value.format_as_string(value, object, object.bytesize)
|
53
|
+
when Hash
|
54
|
+
Bolt::Value.format_as_dictionary(value, object.size)
|
55
|
+
object.each_with_index do |(key, elem), index|
|
56
|
+
key = key.to_s
|
57
|
+
Bolt::Dictionary.set_key(value, index, key, key.bytesize)
|
58
|
+
to_neo(Bolt::Dictionary.value(value, index), elem)
|
59
|
+
end
|
60
|
+
when Types::Path
|
61
|
+
Exceptions::ClientException.unable_to_convert(object)
|
62
|
+
when Enumerable
|
63
|
+
object = object.to_a
|
64
|
+
Bolt::Value.format_as_list(value, object.size)
|
65
|
+
object.each_with_index { |elem, index| to_neo(Bolt::List.value(value, index), elem) }
|
66
|
+
when Date
|
67
|
+
DateValue.to_neo(value, object)
|
68
|
+
when ActiveSupport::Duration
|
69
|
+
DurationValue.to_neo(value, object)
|
70
|
+
when Neo4j::Driver::Types::Point
|
71
|
+
case object.coordinates.size
|
72
|
+
when 2
|
73
|
+
Point2DValue
|
74
|
+
when 3
|
75
|
+
Point3DValue
|
76
|
+
else
|
77
|
+
raise Exception
|
78
|
+
end&.to_neo(value, object)
|
79
|
+
when Types::OffsetTime
|
80
|
+
OffsetTimeValue.to_neo(value, object)
|
81
|
+
when Types::LocalTime
|
82
|
+
LocalTimeValue.to_neo(value, object)
|
83
|
+
when Types::LocalDateTime
|
84
|
+
LocalDateTimeValue.to_neo(value, object)
|
85
|
+
when ActiveSupport::TimeWithZone
|
86
|
+
TimeWithZoneIdValue.to_neo(value, object)
|
87
|
+
when Time
|
88
|
+
TimeWithZoneOffsetValue.to_neo(value, object)
|
89
|
+
else
|
90
|
+
Exceptions::ClientException.unable_to_convert(object)
|
91
|
+
end
|
92
|
+
value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
class Statement
|
6
|
+
attr_reader :text, :parameters
|
7
|
+
|
8
|
+
def initialize(text, parameters = nil)
|
9
|
+
Internal::Validator.require_hash_parameters!(parameters)
|
10
|
+
@text = text
|
11
|
+
@parameters = parameters || {}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Types
|
6
|
+
class Entity
|
7
|
+
attr_reader :id, :properties
|
8
|
+
delegate :[], to: :properties
|
9
|
+
|
10
|
+
def initialize(id, properties)
|
11
|
+
@id = id
|
12
|
+
@properties = properties
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
self.class == other.class && id == other.id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Types
|
6
|
+
class Path < Array
|
7
|
+
attr_reader :modes, :relationships
|
8
|
+
|
9
|
+
class Segment
|
10
|
+
attr_reader :start_node, :relationship, :end_node
|
11
|
+
|
12
|
+
def initialize(start_node, relationship, end_node)
|
13
|
+
@start_node = start_node
|
14
|
+
@relationship = relationship
|
15
|
+
@end_node = end_node
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(nodes, relationships)
|
20
|
+
super()
|
21
|
+
@nodes = nodes
|
22
|
+
@relationships = relationships
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_node
|
26
|
+
@nodes.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def end_node
|
30
|
+
@nodes.last
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Types
|
6
|
+
class Relationship < Entity
|
7
|
+
attr_accessor :start_node_id, :end_node_id
|
8
|
+
attr_reader :type
|
9
|
+
|
10
|
+
def initialize(id, start_node_id, end_node_id, type, properties)
|
11
|
+
super(id, properties)
|
12
|
+
@start_node_id = start_node_id
|
13
|
+
@end_node_id = end_node_id
|
14
|
+
@type = type.to_sym
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/loader.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zeitwerk'
|
4
|
+
|
5
|
+
class Loader
|
6
|
+
def self.load
|
7
|
+
loader = Zeitwerk::Loader.new
|
8
|
+
loader.tag = 'neo4j-ruby-driver'
|
9
|
+
loader.push_dir(File.expand_path(__dir__))
|
10
|
+
loader.push_dir(File.dirname(File.dirname(caller_locations(1..1).first.path)))
|
11
|
+
loader.ignore(File.expand_path('neo4j-java-driver_jars.rb', __dir__))
|
12
|
+
loader.ignore(File.expand_path('neo4j_ruby_driver.rb', __dir__))
|
13
|
+
loader.ignore(File.expand_path('org', __dir__))
|
14
|
+
loader.inflector = Zeitwerk::GemInflector.new(File.expand_path('neo4j/driver', __dir__))
|
15
|
+
loader.setup
|
16
|
+
loader.eager_load
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module AutoClosable
|
6
|
+
def auto_closable(*methods)
|
7
|
+
prepend with_block_definer(methods)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def with_block_definer(methods)
|
13
|
+
Module.new do
|
14
|
+
methods.each do |method|
|
15
|
+
define_method(method) do |*args, &block|
|
16
|
+
closable = super(*args)
|
17
|
+
if block
|
18
|
+
begin
|
19
|
+
block.arity.zero? ? closable.instance_eval(&block) : block.call(closable)
|
20
|
+
ensure
|
21
|
+
closable&.close
|
22
|
+
end
|
23
|
+
else
|
24
|
+
closable
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Exceptions
|
6
|
+
class ClientException < Neo4jException
|
7
|
+
class << self
|
8
|
+
def unable_to_convert(object)
|
9
|
+
raise self, "Unable to convert #{object.class.name} to Neo4j Value."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Exceptions
|
6
|
+
class Neo4jException < RuntimeError
|
7
|
+
attr_reader :code, :cause, :suppressed
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
@code = args.shift if args.count > 1
|
11
|
+
message = args.shift
|
12
|
+
@cause = args.shift
|
13
|
+
@suppressed = args.shift
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_suppressed(exception)
|
18
|
+
(@suppressed ||= []) << exception
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neo4j
|
4
|
+
module Driver
|
5
|
+
module Exceptions
|
6
|
+
class NoSuchRecordException < RuntimeError
|
7
|
+
EMPTY = 'Cannot retrieve a single record, because this result is empty.'
|
8
|
+
TOO_MANY = 'Expected a result with a single record, but this result ' \
|
9
|
+
'contains at least one more. Ensure your query returns only one record.'
|
10
|
+
NO_MORE = 'No more records'
|
11
|
+
NO_PEEK_PAST = 'Cannot peek past the last record'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def empty
|
15
|
+
new(EMPTY)
|
16
|
+
end
|
17
|
+
|
18
|
+
def too_many
|
19
|
+
new(TOO_MANY)
|
20
|
+
end
|
21
|
+
|
22
|
+
def no_more
|
23
|
+
new(NO_MORE)
|
24
|
+
end
|
25
|
+
|
26
|
+
def no_peek_past
|
27
|
+
new(NO_PEEK_PAST)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|