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
data/lib/dse/graph.rb
ADDED
@@ -0,0 +1,18 @@
|
|
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
|
+
require 'dse/graph/edge'
|
11
|
+
require 'dse/graph/options'
|
12
|
+
require 'dse/graph/path'
|
13
|
+
require 'dse/graph/result'
|
14
|
+
require 'dse/graph/result_set'
|
15
|
+
require 'dse/graph/statement'
|
16
|
+
require 'dse/graph/vertex'
|
17
|
+
require 'dse/graph/vertex_property'
|
18
|
+
require 'dse/graph/duration'
|
@@ -0,0 +1,131 @@
|
|
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
|
+
# Represents a duration of time, corresponding to the Duration datatype in DSE Graph. In DSE Graph,
|
13
|
+
# this type is represented by the
|
14
|
+
# {https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html Java 8 Duration} type.
|
15
|
+
class Duration
|
16
|
+
# Days in duration of time. May be negative. Is internally coerced to an integer,
|
17
|
+
# so a value being assigned need not be an `Integer` itself.
|
18
|
+
# @return [Integer] days in duration of time.
|
19
|
+
attr_reader :days
|
20
|
+
|
21
|
+
# Hours in duration of time. May be negative. Is internally coerced to an integer,
|
22
|
+
# so a value being assigned need not be an `Integer` itself.
|
23
|
+
# @return [Integer] hours in duration of time.
|
24
|
+
attr_reader :hours
|
25
|
+
|
26
|
+
# Minutes in duration of time. May be negative. Is internally coerced to an integer,
|
27
|
+
# so a value being assigned need not be an `Integer` itself.
|
28
|
+
# @return [Integer] minutes in duration of time.
|
29
|
+
attr_reader :minutes
|
30
|
+
|
31
|
+
# Seconds in duration of time. May be negative. Is internally coerced to an float,
|
32
|
+
# so a value being assigned need not be an `Float` itself.
|
33
|
+
# @return [Float] seconds in duration of time.
|
34
|
+
attr_reader :seconds
|
35
|
+
|
36
|
+
# @private
|
37
|
+
# We expect a string of the form PnDTnHnMn.nS, where n's are positive or negative integers, and where
|
38
|
+
# components may be missing (e.g. PT7.8S is valid)
|
39
|
+
PAT = /^P((?<days>-?\d+)D)?T((?<hours>-?\d+)H)?((?<minutes>-?\d+)M)?((?<seconds>-?[0-9.]+)S)?$/
|
40
|
+
|
41
|
+
# Create a {Duration} object. All arguments are internally coerced to desired types.
|
42
|
+
# @param days [Integer] number of days in the time-frame. May be negative.
|
43
|
+
# @param hours [Integer] number of hours in the time-frame. May be negative.
|
44
|
+
# @param minutes [Integer] number of minutes in the time-frame. May be negative.
|
45
|
+
# @param seconds [Float] number of seconds in the time-frame. May be negative.
|
46
|
+
def initialize(days, hours, minutes, seconds)
|
47
|
+
@days = days.to_i
|
48
|
+
@hours = hours.to_i
|
49
|
+
@minutes = minutes.to_i
|
50
|
+
@seconds = seconds.to_f
|
51
|
+
end
|
52
|
+
|
53
|
+
def days=(days)
|
54
|
+
@days = days.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
def hours=(hours)
|
58
|
+
@hours = hours.to_i
|
59
|
+
end
|
60
|
+
|
61
|
+
def minutes=(minutes)
|
62
|
+
@minutes = minutes.to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
def seconds=(seconds)
|
66
|
+
@seconds = seconds.to_f
|
67
|
+
end
|
68
|
+
|
69
|
+
# Parse a duration string from DSE Graph and construct a {Duration} object
|
70
|
+
# @param duration [String] duration string from DSE Graph.
|
71
|
+
# @raise [ArgumentError] if the duration string fails to parse.
|
72
|
+
def self.parse(duration)
|
73
|
+
parse_result = PAT.match(duration.to_s)
|
74
|
+
raise(ArgumentError,
|
75
|
+
"Failed to parse '#{duration}': expected format PnDTnHnMn.nS with integer n" \
|
76
|
+
' and optionally missing duration components') unless parse_result
|
77
|
+
Duration.new(parse_result[:days], parse_result[:hours], parse_result[:minutes], parse_result[:seconds])
|
78
|
+
end
|
79
|
+
|
80
|
+
# A string formatted as `PnDTnHnMn.nS`, where `n` is a number that goes with the character code following it.
|
81
|
+
#
|
82
|
+
# D - days<br>
|
83
|
+
# H - hours<br>
|
84
|
+
# M - minutes<br>
|
85
|
+
# S - seconds<br>
|
86
|
+
#
|
87
|
+
# @example a duration of 1 day, 2 hours, 3 minutes, 4.5 seconds
|
88
|
+
# P1DT2H3M4.5S
|
89
|
+
# @return [String] this {Duration} as a string formatted `PnDTnHnMn.nS`.
|
90
|
+
#
|
91
|
+
# @see https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-
|
92
|
+
# Java 8 Duration#parse
|
93
|
+
def to_s
|
94
|
+
# Construct a string of the form PnDTnHnMn.nS
|
95
|
+
"P#{@days}DT#{@hours}H#{@minutes}M#{@seconds}S"
|
96
|
+
end
|
97
|
+
|
98
|
+
# @private
|
99
|
+
def eql?(other)
|
100
|
+
other.is_a?(Duration) && as_seconds == other.as_seconds
|
101
|
+
end
|
102
|
+
alias == eql?
|
103
|
+
|
104
|
+
# @return [Float] this {Duration} object converted to seconds
|
105
|
+
def as_seconds
|
106
|
+
@seconds + @minutes * 60 + @hours * 3600 + @days * 86400
|
107
|
+
end
|
108
|
+
|
109
|
+
# @private
|
110
|
+
def hash
|
111
|
+
@hash ||= begin
|
112
|
+
h = 17
|
113
|
+
h = 31 * h + @days.hash
|
114
|
+
h = 31 * h + @hours.hash
|
115
|
+
h = 31 * h + @minutes.hash
|
116
|
+
h = 31 * h + @seconds.hash
|
117
|
+
h
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @private
|
122
|
+
def inspect
|
123
|
+
"#<Duration:0x#{object_id.to_s(16)} " \
|
124
|
+
"@days=#{@days.inspect}, " \
|
125
|
+
"@hours=#{@hours.inspect}, " \
|
126
|
+
"@minutes=#{@minutes.inspect}, " \
|
127
|
+
"@seconds=#{@seconds.inspect}>"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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
|
+
# Edge represents an edge in DSE graph. An edge connects two vertices.
|
13
|
+
class Edge
|
14
|
+
include Cassandra::Util
|
15
|
+
|
16
|
+
# @return [Hash] id of this edge
|
17
|
+
attr_reader :id
|
18
|
+
# @return [String] label of this edge
|
19
|
+
attr_reader :label
|
20
|
+
# @return [Hash<String, String>] properties of this edge
|
21
|
+
attr_reader :properties
|
22
|
+
# @return [String] id of the "to" vertex of the edge
|
23
|
+
attr_reader :in_v
|
24
|
+
# @return [String] label of the "to" vertex of the edge
|
25
|
+
attr_reader :in_v_label
|
26
|
+
# @return [String] id of the "from" vertex of the edge
|
27
|
+
attr_reader :out_v
|
28
|
+
# @return [String] label of the "from" vertex of the edge
|
29
|
+
attr_reader :out_v_label
|
30
|
+
|
31
|
+
# @private
|
32
|
+
def initialize(id, label, properties, in_v, in_v_label, out_v, out_v_label)
|
33
|
+
@id = id
|
34
|
+
@label = label
|
35
|
+
@properties = properties
|
36
|
+
@in_v = in_v
|
37
|
+
@in_v_label = in_v_label
|
38
|
+
@out_v = out_v
|
39
|
+
@out_v_label = out_v_label
|
40
|
+
end
|
41
|
+
|
42
|
+
# @private
|
43
|
+
def [](key)
|
44
|
+
@properties[key]
|
45
|
+
end
|
46
|
+
|
47
|
+
# @private
|
48
|
+
def eql?(other)
|
49
|
+
# id's are unique among graph objects, so we only need to compare id's to test for equality.
|
50
|
+
other.is_a?(Edge) && \
|
51
|
+
@id == other.id
|
52
|
+
end
|
53
|
+
alias == eql?
|
54
|
+
|
55
|
+
# @private
|
56
|
+
def hash
|
57
|
+
# id's are unique among graph objects, so we only need to hash on the id for safely adding to a hash/set.
|
58
|
+
@hash ||= 31 * 17 + @id.hash
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
def inspect
|
63
|
+
"#<Dse::Graph::Edge:0x#{object_id.to_s(16)} " \
|
64
|
+
"@id=#{@id.inspect}, " \
|
65
|
+
"@label=#{@label.inspect}, " \
|
66
|
+
"@properties=#{@properties.inspect}, " \
|
67
|
+
"@in_v=#{@in_v.inspect}, " \
|
68
|
+
"@in_v_label=#{@in_v_label.inspect}, " \
|
69
|
+
"@out_v=#{@out_v.inspect}, " \
|
70
|
+
"@out_v_label=#{@out_v_label.inspect}>"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,194 @@
|
|
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
|
+
# @!parse
|
13
|
+
# class Options
|
14
|
+
# # @return [String] name of the targeted graph; required unless the statement is a system query.
|
15
|
+
# attr_accessor :graph_name
|
16
|
+
# # @return [String] graph traversal source (default "g")
|
17
|
+
# attr_accessor :graph_source
|
18
|
+
# # @return [String] language used in the graph statement (default "gremlin-groovy")
|
19
|
+
# attr_accessor :graph_language
|
20
|
+
# # @return [Cassandra::CONSISTENCIES] read consistency level for graph statement.
|
21
|
+
# # Overrides the standard statement consistency level. Defaults to ONE in the server,
|
22
|
+
# # but the default may be configured differently.
|
23
|
+
# attr_accessor :graph_read_consistency
|
24
|
+
# # @return [Cassandra::CONSISTENCIES] write consistency level for graph statement.
|
25
|
+
# # Overrides the standard statement consistency level. Defaults to QUORUM in the server,
|
26
|
+
# # but the default may be configured differently.
|
27
|
+
# attr_accessor :graph_write_consistency
|
28
|
+
# end
|
29
|
+
|
30
|
+
# Options for DSE Graph queries
|
31
|
+
class Options
|
32
|
+
# @return [Numeric] the timeout for graph requests
|
33
|
+
attr_reader :timeout
|
34
|
+
|
35
|
+
# @private
|
36
|
+
DEFAULT_GRAPH_OPTIONS = {
|
37
|
+
'graph-source' => 'g',
|
38
|
+
'graph-language' => 'gremlin-groovy'
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
# @private
|
42
|
+
OPTION_NAMES = [
|
43
|
+
:graph_name,
|
44
|
+
:graph_source,
|
45
|
+
:graph_language,
|
46
|
+
:graph_read_consistency,
|
47
|
+
:graph_write_consistency
|
48
|
+
].freeze
|
49
|
+
|
50
|
+
# Create an Options object.
|
51
|
+
# @param options [Hash] optional hash containing graph options. Keys are option name symbols
|
52
|
+
# (e.g. `:graph_name`). Unset options will inherit from the defaults.
|
53
|
+
def initialize(options = {})
|
54
|
+
# Filter the given options to only those we care about.
|
55
|
+
@real_options = {}
|
56
|
+
return unless options
|
57
|
+
|
58
|
+
options.each do |k, v|
|
59
|
+
set(k, v) if OPTION_NAMES.include?(k)
|
60
|
+
end
|
61
|
+
|
62
|
+
set_timeout(options[:timeout])
|
63
|
+
end
|
64
|
+
|
65
|
+
OPTION_NAMES.each do |attr|
|
66
|
+
define_method(attr.to_s) do
|
67
|
+
@real_options[stringify(attr)]
|
68
|
+
end
|
69
|
+
|
70
|
+
define_method("#{attr}=") do |value|
|
71
|
+
@real_options[stringify(attr)] = value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @private
|
76
|
+
def timeout=(val)
|
77
|
+
set_timeout(val)
|
78
|
+
val
|
79
|
+
end
|
80
|
+
|
81
|
+
# @private
|
82
|
+
# rubocop:disable Style/AccessorMethodName
|
83
|
+
def set_timeout(new_timeout)
|
84
|
+
@timeout = new_timeout
|
85
|
+
if @timeout
|
86
|
+
@real_options['request-timeout'] = [@timeout * 1000].pack('Q>')
|
87
|
+
else
|
88
|
+
@real_options.delete('request-timeout')
|
89
|
+
end
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Set an option in this {Options} object. This is primarily used to set "expert" options that
|
94
|
+
# are not part of the public api and thus may change over time.
|
95
|
+
# @param key [String, Symbol] option to set.
|
96
|
+
# @param value [String] value to set for the option.
|
97
|
+
# @return [Options] self, thus allowing method chaining.
|
98
|
+
def set(key, value)
|
99
|
+
string_key = stringify(key)
|
100
|
+
if string_key == 'timeout'
|
101
|
+
set_timeout(value)
|
102
|
+
elsif value
|
103
|
+
@real_options[stringify(key)] = value
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
# Delete an option from this {Options} object.
|
109
|
+
# @param key [String, Symbol] option to delete.
|
110
|
+
# @return nil
|
111
|
+
def delete(key)
|
112
|
+
string_key = stringify(key)
|
113
|
+
if string_key == 'timeout'
|
114
|
+
@timeout = nil
|
115
|
+
@real_options.delete('request-timeout')
|
116
|
+
else
|
117
|
+
@real_options.delete(string_key)
|
118
|
+
end
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
# Merge another {Options} object with this one to produce a new merged {Options} object.
|
123
|
+
# The "other" object's values take precedence over this one.
|
124
|
+
# @param other [Options] Options object to merge with this one.
|
125
|
+
# @return [Options] new Options object with the merged options.
|
126
|
+
def merge(other)
|
127
|
+
# Just return our-self (no need to copy) if we're merging in nothing.
|
128
|
+
return self if other.nil?
|
129
|
+
|
130
|
+
# This is fairly efficient, but manipulates the guts of an Options object.
|
131
|
+
result = Options.new
|
132
|
+
result.instance_variable_set(:@real_options,
|
133
|
+
@real_options.merge(other.instance_variable_get(:@real_options)))
|
134
|
+
other_timeout = other.instance_variable_get(:@timeout)
|
135
|
+
result.instance_variable_set(:@timeout,
|
136
|
+
other_timeout ? other_timeout : @timeout)
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
# Clear the options within this {Options} object.
|
141
|
+
def clear
|
142
|
+
@real_options.clear
|
143
|
+
@timeout = nil
|
144
|
+
end
|
145
|
+
|
146
|
+
# @private
|
147
|
+
def stringify(attr)
|
148
|
+
attr.to_s.tr('_', '-')
|
149
|
+
end
|
150
|
+
|
151
|
+
# @private
|
152
|
+
def merge!(other)
|
153
|
+
result = merge(other)
|
154
|
+
@real_options = result.instance_variable_get(:@real_options)
|
155
|
+
@timeout = result.instance_variable_get(:@timeout)
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return whether or not this options object is configured for the analytics graph source.
|
160
|
+
def analytics?
|
161
|
+
@real_options['graph-source'] == 'a'
|
162
|
+
end
|
163
|
+
|
164
|
+
# @private
|
165
|
+
def as_payload
|
166
|
+
# Merge in real options with defaults to get a final payload
|
167
|
+
DEFAULT_GRAPH_OPTIONS.merge(@real_options)
|
168
|
+
end
|
169
|
+
|
170
|
+
# @private
|
171
|
+
def eql?(other)
|
172
|
+
other.is_a?(Options) && \
|
173
|
+
@real_options == other.instance_variable_get(:@real_options)
|
174
|
+
end
|
175
|
+
alias == eql?
|
176
|
+
|
177
|
+
# @private
|
178
|
+
def hash
|
179
|
+
@hash ||= 31 * 17 + @real_options.hash
|
180
|
+
end
|
181
|
+
|
182
|
+
# @private
|
183
|
+
def inspect
|
184
|
+
"#<Dse::Graph::Options:0x#{object_id.to_s(16)} " \
|
185
|
+
"@graph_name=#{@real_options['graph-name'].inspect}, " \
|
186
|
+
"@graph_source=#{@real_options['graph-source'].inspect}, " \
|
187
|
+
"@graph_language=#{@real_options['graph-language'].inspect}, " \
|
188
|
+
"@graph_read_consistency=#{@real_options['graph-read-consistency'].inspect}, " \
|
189
|
+
"@graph_write_consistency=#{@real_options['graph-write-consistency'].inspect}, " \
|
190
|
+
"@timeout=#{@timeout.inspect}>"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,54 @@
|
|
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
|
+
# Path represents a path connecting a set of vertices.
|
13
|
+
class Path
|
14
|
+
# @return [Array<Array>] labels in the path
|
15
|
+
attr_reader :labels
|
16
|
+
# @return [Array<Vertex, Edge, Result>] objects in the path, coerced to domain objects that
|
17
|
+
# we recognize, or a {Result} otherwise
|
18
|
+
attr_reader :objects
|
19
|
+
|
20
|
+
# @private
|
21
|
+
def initialize(labels, objects)
|
22
|
+
@labels = labels
|
23
|
+
@objects = objects.map do |o|
|
24
|
+
Result.new(o).cast
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @private
|
29
|
+
def eql?(other)
|
30
|
+
other.is_a?(Path) && \
|
31
|
+
@labels == other.labels && \
|
32
|
+
@objects == other.objects
|
33
|
+
end
|
34
|
+
alias == eql?
|
35
|
+
|
36
|
+
# @private
|
37
|
+
def hash
|
38
|
+
@hash ||= begin
|
39
|
+
h = 17
|
40
|
+
h = 31 * h + @labels.hash
|
41
|
+
h = 31 * h + @objects.hash
|
42
|
+
h
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @private
|
47
|
+
def inspect
|
48
|
+
"#<Dse::Graph::Path:0x#{object_id.to_s(16)} " \
|
49
|
+
"@labels=#{@labels.inspect}, " \
|
50
|
+
"@objects=#{@objects.inspect}>"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|