dse-driver 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|