dse-driver 1.0.1
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 +15 -0
- data/.yardopts +13 -0
- data/README.md +72 -0
- data/ext/gss_api_context/extconf.rb +27 -0
- data/ext/gss_api_context/gss_api_context.c +129 -0
- data/ext/gss_api_context/kerberosgss.c +407 -0
- data/ext/gss_api_context/kerberosgss.h +71 -0
- data/lib/dse.rb +104 -0
- data/lib/dse/auth/providers/gss_api.rb +160 -0
- data/lib/dse/auth/providers/password.rb +56 -0
- data/lib/dse/cluster.rb +99 -0
- data/lib/dse/geometry/line_string.rb +181 -0
- data/lib/dse/geometry/point.rb +179 -0
- data/lib/dse/geometry/polygon.rb +196 -0
- data/lib/dse/graph.rb +18 -0
- data/lib/dse/graph/duration.rb +131 -0
- data/lib/dse/graph/edge.rb +74 -0
- data/lib/dse/graph/options.rb +194 -0
- data/lib/dse/graph/path.rb +54 -0
- data/lib/dse/graph/result.rb +85 -0
- data/lib/dse/graph/result_set.rb +77 -0
- data/lib/dse/graph/statement.rb +118 -0
- data/lib/dse/graph/vertex.rb +107 -0
- data/lib/dse/graph/vertex_property.rb +66 -0
- data/lib/dse/load_balancing/policies/host_targeting.rb +102 -0
- data/lib/dse/session.rb +106 -0
- data/lib/dse/statements.rb +15 -0
- data/lib/dse/statements/host_targeting.rb +50 -0
- data/lib/dse/util.rb +12 -0
- data/lib/dse/util/endian_buffer.rb +37 -0
- data/lib/dse/version.rb +12 -0
- metadata +123 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2016 DataStax Inc.
|
5
|
+
#
|
6
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
7
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
8
|
+
#++
|
9
|
+
|
10
|
+
module Dse
|
11
|
+
module Graph
|
12
|
+
# An individual result of running a graph query. It wraps the JSON result and provides
|
13
|
+
# access to it as a hash. It also supports casting the result into a known
|
14
|
+
# domain object type: {Vertex}, {Edge}, and {Path} currently.
|
15
|
+
#
|
16
|
+
# @see ResultSet
|
17
|
+
class Result
|
18
|
+
# @return hash representation of the JSON result of a graph query if it's a complex result. A simple value
|
19
|
+
# otherwise
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
# @private
|
23
|
+
def initialize(result)
|
24
|
+
@value = result
|
25
|
+
end
|
26
|
+
|
27
|
+
# Coerce this result into a domain object if possible.
|
28
|
+
# @return [Vertex, Edge, Result] a new wrapped object, or self if we can't cast it
|
29
|
+
def cast
|
30
|
+
type = @value['type'] if @value.is_a?(Hash)
|
31
|
+
case type
|
32
|
+
when 'vertex'
|
33
|
+
as_vertex
|
34
|
+
when 'edge'
|
35
|
+
as_edge
|
36
|
+
else
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Coerce this result into a {Vertex} object.
|
42
|
+
# @return [Vertex] a vertex domain object
|
43
|
+
# @raise [ArgumentError] if the result data does not represent a vertex
|
44
|
+
def as_vertex
|
45
|
+
Cassandra::Util.assert_instance_of(::Hash, @value)
|
46
|
+
Dse::Graph::Vertex.new(@value['id'], @value['label'], @value.fetch('properties', {}))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Coerce this result into an {Edge} object.
|
50
|
+
# @return [Edge] an edge domain object.
|
51
|
+
# @raise [ArgumentError] if the result data does not represent an edge.
|
52
|
+
def as_edge
|
53
|
+
Cassandra::Util.assert_instance_of(::Hash, @value)
|
54
|
+
Dse::Graph::Edge.new(@value['id'], @value['label'], @value.fetch('properties', {}),
|
55
|
+
@value['inV'], @value['inVLabel'],
|
56
|
+
@value['outV'], @value['outVLabel'])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Coerce this result into a {Path} object.
|
60
|
+
# @return [Path] a path domain object.
|
61
|
+
def as_path
|
62
|
+
Cassandra::Util.assert_instance_of(::Hash, @value)
|
63
|
+
Dse::Graph::Path.new(@value['labels'], @value['objects'])
|
64
|
+
end
|
65
|
+
|
66
|
+
# @private
|
67
|
+
def eql?(other)
|
68
|
+
other.is_a?(Result) && \
|
69
|
+
@value == other.value
|
70
|
+
end
|
71
|
+
alias == eql?
|
72
|
+
|
73
|
+
# @private
|
74
|
+
def hash
|
75
|
+
@hash ||= 31 * 17 + @value.hash
|
76
|
+
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
def inspect
|
80
|
+
"#<Dse::Graph::Result:0x#{object_id.to_s(16)} " \
|
81
|
+
"@value=#{@value.inspect}>"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2016 DataStax Inc.
|
5
|
+
#
|
6
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
7
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
8
|
+
#++
|
9
|
+
|
10
|
+
module Dse
|
11
|
+
module Graph
|
12
|
+
# Collection of results of running a graph query. It wraps a {Cassandra::Result}. When iterating
|
13
|
+
# over results, individual results may be well-known domain objects or a generic {Result}.
|
14
|
+
#
|
15
|
+
# @see Vertex
|
16
|
+
# @see Edge
|
17
|
+
# @see Path
|
18
|
+
# @see Result
|
19
|
+
class ResultSet
|
20
|
+
include Enumerable
|
21
|
+
extend Forwardable
|
22
|
+
|
23
|
+
# @private -- just for ==/eql?
|
24
|
+
attr_reader :parsed_results
|
25
|
+
|
26
|
+
# @!method execution_info
|
27
|
+
# Query execution information, such as number of retries and all tried hosts, etc.
|
28
|
+
# @return [Cassandra::Execution::Info]
|
29
|
+
#
|
30
|
+
# @!method empty?
|
31
|
+
# @return [Boolean] whether it has any result data
|
32
|
+
#
|
33
|
+
# @!method size
|
34
|
+
# @return [Integer] number of results
|
35
|
+
#
|
36
|
+
def_delegators :@results, :execution_info, :empty?, :size
|
37
|
+
alias length size
|
38
|
+
|
39
|
+
# @private
|
40
|
+
def initialize(results)
|
41
|
+
@results = results
|
42
|
+
@parsed_results = results.map do |r|
|
43
|
+
Result.new(JSON.parse(r.fetch('gremlin', {})).fetch('result', {})).cast
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @yieldparam result [Vertex, Edge, Path, Result] result object for a particular result
|
48
|
+
# @return [Enumerator, self] returns Enumerator if no block given
|
49
|
+
def each(&block)
|
50
|
+
@parsed_results.each(&block)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Allow array indexing into the result-set.
|
54
|
+
# @param ind [Integer] index into the collection of query results.
|
55
|
+
def [](ind)
|
56
|
+
@parsed_results[ind]
|
57
|
+
end
|
58
|
+
|
59
|
+
# @private
|
60
|
+
def eql?(other)
|
61
|
+
other.is_a?(ResultSet) && \
|
62
|
+
@parsed_results == other.parsed_results
|
63
|
+
end
|
64
|
+
alias == eql?
|
65
|
+
|
66
|
+
# @private
|
67
|
+
def hash
|
68
|
+
@hash ||= 31 * 17 + @parsed_results.hash
|
69
|
+
end
|
70
|
+
|
71
|
+
# @private
|
72
|
+
def inspect
|
73
|
+
"#<Dse::ResultSet:0x#{object_id.to_s(16)} []=#{@parsed_results.inspect}>"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2016 DataStax Inc.
|
5
|
+
#
|
6
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
7
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
8
|
+
#++
|
9
|
+
|
10
|
+
module Dse
|
11
|
+
module Graph
|
12
|
+
# Encapsulates a graph statement, parameters, options, and idempotency. This is primarily useful for
|
13
|
+
# re-issuing the same statement multiple times the same way.
|
14
|
+
class Statement
|
15
|
+
include Cassandra::Statement
|
16
|
+
|
17
|
+
# @return [String] graph statement string
|
18
|
+
attr_reader :statement
|
19
|
+
# @return [Hash<String, String>] parameters to the statement
|
20
|
+
attr_reader :parameters
|
21
|
+
# @return [Options] graph options
|
22
|
+
attr_reader :options
|
23
|
+
# @private
|
24
|
+
attr_reader :simple_statement
|
25
|
+
|
26
|
+
# @param statement [String] graph statement
|
27
|
+
# @param parameters [Hash<String, String>] (nil) parameters to the statement
|
28
|
+
# @param options [Hash, Options] (nil) graph options
|
29
|
+
# @param idempotent [Boolean] (false) whether or not the statement is idempotent
|
30
|
+
def initialize(statement, parameters = nil, options = nil, idempotent = false)
|
31
|
+
# Save off statement and idempotent; easy stuff.
|
32
|
+
@statement = statement.freeze
|
33
|
+
@idempotent = idempotent.freeze
|
34
|
+
@parameters = parameters.freeze
|
35
|
+
|
36
|
+
# Convert the parameters into a one-element array with JSON; that's what we need to
|
37
|
+
# send to DSE over the wire. But if we have no params, nil is fine.
|
38
|
+
unless parameters.nil?
|
39
|
+
::Cassandra::Util.assert_instance_of(::Hash, parameters, 'Graph parameters must be a hash')
|
40
|
+
# Some of our parameters may be geo-type values. Convert them to their wkt representation.
|
41
|
+
tweaked_params = {}
|
42
|
+
parameters.each do |name, value|
|
43
|
+
value = value.wkt if value.respond_to?(:wkt)
|
44
|
+
tweaked_params[name] = value
|
45
|
+
end
|
46
|
+
parameters = [tweaked_params.to_json]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Graph options may be tricky. A few cases:
|
50
|
+
# 1. options is nil; then @options should be nil.
|
51
|
+
# 2. options is a Hash with a graph_options key; then @options is the referenced Options object.
|
52
|
+
# We must validate that the referenced object *is* an Options.
|
53
|
+
# 3. options is an Options object; then just assign to @options.
|
54
|
+
|
55
|
+
unless options.nil?
|
56
|
+
Cassandra::Util.assert_instance_of_one_of([Dse::Graph::Options, ::Hash], options)
|
57
|
+
@options = if options.is_a?(Options)
|
58
|
+
options
|
59
|
+
elsif !options[:graph_options].nil?
|
60
|
+
Cassandra::Util.assert_instance_of(Dse::Graph::Options, options[:graph_options])
|
61
|
+
options[:graph_options]
|
62
|
+
else
|
63
|
+
Dse::Graph::Options.new(options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
@simple_statement = Cassandra::Statements::Simple.new(@statement,
|
68
|
+
parameters,
|
69
|
+
parameters.nil? ? nil : [Cassandra::Types.varchar],
|
70
|
+
@idempotent)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @private
|
74
|
+
def accept(client, options)
|
75
|
+
simple_statement.accept(client, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
def eql?(other)
|
80
|
+
other.is_a?(Statement) && \
|
81
|
+
@statement == other.statement && \
|
82
|
+
@parameters == other.parameters && \
|
83
|
+
@options == other.options && \
|
84
|
+
@idempotent == other.idempotent?
|
85
|
+
end
|
86
|
+
alias == eql?
|
87
|
+
|
88
|
+
# @private
|
89
|
+
def hash
|
90
|
+
@hash ||= begin
|
91
|
+
h = 17
|
92
|
+
h = 31 * h + @statement.hash
|
93
|
+
h = 31 * h + @parameters.hash
|
94
|
+
h = 31 * h + @options.hash
|
95
|
+
h = 31 * h + @idempotent.hash
|
96
|
+
h
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# @private
|
101
|
+
def inspect
|
102
|
+
"#<Dse::Graph::Statement:0x#{object_id.to_s(16)} " \
|
103
|
+
"@statement=#{@statement.inspect}, " \
|
104
|
+
"@parameters=#{@parameters.inspect}, " \
|
105
|
+
"@options=#{@options.inspect}, " \
|
106
|
+
"@idempotent=#{@idempotent.inspect}>"
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
# @private
|
112
|
+
def method_missing(method, *args, &block)
|
113
|
+
# Delegate unrecognized method calls to our embedded statement.
|
114
|
+
@simple_statement.send(method, *args, &block)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2016 DataStax Inc.
|
5
|
+
#
|
6
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
7
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
8
|
+
#++
|
9
|
+
|
10
|
+
module Dse
|
11
|
+
module Graph
|
12
|
+
# Vertex represents a vertex in DSE graph. Vertices have sophisticated properties. A given property can have
|
13
|
+
# multiple values, and each value can have a collection of meta-properties. To access a property of a vertex, you'd
|
14
|
+
# reference the {#properties} hash, and then get the n'th value, which is a {VertexProperty}, and then get the
|
15
|
+
# actual value from there.
|
16
|
+
# @example To get the first value of the 'name' property:
|
17
|
+
# v.properties['name'][0].value
|
18
|
+
# @example Use array/hash dereference shortcut
|
19
|
+
# v['name'][0].value
|
20
|
+
# @example Get all of the values of the 'name' property
|
21
|
+
# values = v['name'].map do |vertex_prop|
|
22
|
+
# vertex_prop.value
|
23
|
+
# end
|
24
|
+
# @example Use the 'values' method on the array to do the heavy-lifting for you.
|
25
|
+
# values = v['name'].values
|
26
|
+
# @example VertexProperty exposes meta-properties for a value:
|
27
|
+
# meta1 = v['name'][0].properties['meta1']
|
28
|
+
# # Shortcut
|
29
|
+
# meta1 = v['name'][0]['meta1']
|
30
|
+
class Vertex
|
31
|
+
include Cassandra::Util
|
32
|
+
|
33
|
+
# @return [Hash] id of this vertex.
|
34
|
+
attr_reader :id
|
35
|
+
# @return [String] label of this vertex.
|
36
|
+
attr_reader :label
|
37
|
+
# @return [Hash<String, Array<VertexProperty>>] properties of this vertex.
|
38
|
+
attr_reader :properties
|
39
|
+
|
40
|
+
# @private
|
41
|
+
def initialize(id, label, properties)
|
42
|
+
@id = id
|
43
|
+
@label = label
|
44
|
+
|
45
|
+
# Vertex properties are structured like this:
|
46
|
+
# { 'name' => [
|
47
|
+
# { 'id' => {... }, 'value' => 'some_val', 'properties' => { 'key' => 'value' } },
|
48
|
+
# { 'id' => {... }, 'value' => 'some_val2', 'properties' => { 'key2' => 'value2' } }
|
49
|
+
# ], 'age' => [........], .... }
|
50
|
+
#
|
51
|
+
# When storing in @properties, we convert it to use VertexProperty's:
|
52
|
+
# { 'name' => [
|
53
|
+
# vertex_prop1,
|
54
|
+
# vertex_prop2
|
55
|
+
# ], 'age' => [........], .... }
|
56
|
+
#
|
57
|
+
# With that structure, we'll support syntactic sugar that lets users get to properties and meta-properties
|
58
|
+
# more easily:
|
59
|
+
#
|
60
|
+
# v['name'][0].value -- get the first value of the 'name' property.
|
61
|
+
# v['name'][0]['key'] -- get the value of the 'key' meta-property of the first name property.
|
62
|
+
|
63
|
+
@properties = {}
|
64
|
+
properties.each do |prop_name, values|
|
65
|
+
vertex_props = values.map do |v|
|
66
|
+
VertexProperty.new(v)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Add a 'values' method to the array to get the values of each prop
|
70
|
+
# in one array.
|
71
|
+
def vertex_props.values
|
72
|
+
map(&:value)
|
73
|
+
end
|
74
|
+
|
75
|
+
@properties[prop_name] = vertex_props
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# @private
|
80
|
+
def [](key)
|
81
|
+
@properties[key]
|
82
|
+
end
|
83
|
+
|
84
|
+
# @private
|
85
|
+
def eql?(other)
|
86
|
+
# id's are unique among graph objects, so we only need to compare id's to test for equality.
|
87
|
+
other.is_a?(Vertex) && \
|
88
|
+
@id == other.id
|
89
|
+
end
|
90
|
+
alias == eql?
|
91
|
+
|
92
|
+
# @private
|
93
|
+
def hash
|
94
|
+
# id's are unique among graph objects, so we only need to hash on the id for safely adding to a hash/set.
|
95
|
+
@hash ||= 31 * 17 + @id.hash
|
96
|
+
end
|
97
|
+
|
98
|
+
# @private
|
99
|
+
def inspect
|
100
|
+
"#<Dse::Graph::Vertex:0x#{object_id.to_s(16)} " \
|
101
|
+
"@id=#{@id.inspect}, " \
|
102
|
+
"@label=#{@label.inspect}, " \
|
103
|
+
"@properties=#{@properties.inspect}>"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2016 DataStax Inc.
|
5
|
+
#
|
6
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
7
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
8
|
+
#++
|
9
|
+
|
10
|
+
module Dse
|
11
|
+
module Graph
|
12
|
+
# Encapsulates a vertex-property complex value. The name of the property is stored in the owning
|
13
|
+
# {Vertex}. This object contains a simple property value and any meta-properties that go with it.
|
14
|
+
#
|
15
|
+
# VertexProperty's are created when creating a Vertex object out of a graph query result hash. Access
|
16
|
+
# to meta-properties is done via the {#properties} attribute, but there is also a short-cut using
|
17
|
+
# array/hash dereference syntax:
|
18
|
+
# @example
|
19
|
+
# val = vp.properties['meta1']
|
20
|
+
# # is the same as
|
21
|
+
# val = vp['meta1']
|
22
|
+
class VertexProperty
|
23
|
+
# @return [Hash] id of this property
|
24
|
+
attr_reader :id
|
25
|
+
# @return [String] value of this property
|
26
|
+
attr_reader :value
|
27
|
+
# @return [Hash<String, String>] meta-properties of this property
|
28
|
+
attr_reader :properties
|
29
|
+
|
30
|
+
# @private
|
31
|
+
def initialize(vertex_property_hash)
|
32
|
+
# Vertex properties have three attributes: id, value, properties. Pull those out of the hash.
|
33
|
+
@id = vertex_property_hash['id']
|
34
|
+
@value = vertex_property_hash['value']
|
35
|
+
@properties = vertex_property_hash.fetch('properties', {})
|
36
|
+
end
|
37
|
+
|
38
|
+
# @private
|
39
|
+
def [](key)
|
40
|
+
@properties[key]
|
41
|
+
end
|
42
|
+
|
43
|
+
# @private
|
44
|
+
def eql?(other)
|
45
|
+
# id's are unique among graph objects, so we only need to compare id's to test for equality.
|
46
|
+
other.is_a?(VertexProperty) && \
|
47
|
+
@id == other.id
|
48
|
+
end
|
49
|
+
alias == eql?
|
50
|
+
|
51
|
+
# @private
|
52
|
+
def hash
|
53
|
+
# id's are unique among graph objects, so we only need to hash on the id for safely adding to a hash/set.
|
54
|
+
@hash ||= 31 * 17 + @id.hash
|
55
|
+
end
|
56
|
+
|
57
|
+
# @private
|
58
|
+
def inspect
|
59
|
+
"#<Dse::Graph::VertexProperty:0x#{object_id.to_s(16)} " \
|
60
|
+
"@id=#{@id.inspect}, " \
|
61
|
+
"@value=#{@value.inspect}, " \
|
62
|
+
"@properties=#{@properties.inspect}>"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|