cql-rb 1.1.3 → 1.2.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -11
- data/lib/cql.rb +1 -0
- data/lib/cql/client.rb +41 -9
- data/lib/cql/client/asynchronous_client.rb +9 -4
- data/lib/cql/client/asynchronous_prepared_statement.rb +2 -2
- data/lib/cql/client/connection_helper.rb +43 -20
- data/lib/cql/client/execute_options_decoder.rb +4 -1
- data/lib/cql/client/query_result.rb +7 -3
- data/lib/cql/client/query_trace.rb +46 -0
- data/lib/cql/client/request_runner.rb +7 -2
- data/lib/cql/client/void_result.rb +42 -0
- data/lib/cql/compression.rb +53 -0
- data/lib/cql/compression/snappy_compressor.rb +42 -0
- data/lib/cql/io/io_reactor.rb +9 -4
- data/lib/cql/protocol.rb +5 -3
- data/lib/cql/protocol/cql_protocol_handler.rb +14 -9
- data/lib/cql/protocol/frame_decoder.rb +106 -0
- data/lib/cql/protocol/frame_encoder.rb +31 -0
- data/lib/cql/protocol/request.rb +7 -11
- data/lib/cql/protocol/requests/execute_request.rb +2 -2
- data/lib/cql/protocol/requests/options_request.rb +4 -0
- data/lib/cql/protocol/requests/prepare_request.rb +2 -2
- data/lib/cql/protocol/requests/query_request.rb +2 -2
- data/lib/cql/protocol/requests/startup_request.rb +12 -5
- data/lib/cql/protocol/response.rb +13 -2
- data/lib/cql/protocol/responses/authenticate_response.rb +5 -1
- data/lib/cql/protocol/responses/detailed_error_response.rb +2 -2
- data/lib/cql/protocol/responses/error_response.rb +7 -2
- data/lib/cql/protocol/responses/event_response.rb +4 -2
- data/lib/cql/protocol/responses/prepared_result_response.rb +20 -4
- data/lib/cql/protocol/responses/ready_response.rb +5 -1
- data/lib/cql/protocol/responses/result_response.rb +10 -2
- data/lib/cql/protocol/responses/rows_result_response.rb +5 -4
- data/lib/cql/protocol/responses/schema_change_event_response.rb +1 -1
- data/lib/cql/protocol/responses/schema_change_result_response.rb +5 -4
- data/lib/cql/protocol/responses/set_keyspace_result_response.rb +4 -3
- data/lib/cql/protocol/responses/{status_change_event_result_response.rb → status_change_event_response.rb} +1 -1
- data/lib/cql/protocol/responses/supported_response.rb +5 -1
- data/lib/cql/protocol/responses/{topology_change_event_result_response.rb → topology_change_event_response.rb} +0 -0
- data/lib/cql/protocol/responses/void_result_response.rb +2 -2
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/asynchronous_client_spec.rb +52 -31
- data/spec/cql/client/asynchronous_prepared_statement_spec.rb +16 -2
- data/spec/cql/client/connection_helper_spec.rb +90 -12
- data/spec/cql/client/query_trace_spec.rb +138 -0
- data/spec/cql/client/request_runner_spec.rb +44 -7
- data/spec/cql/client/void_result_spec.rb +43 -0
- data/spec/cql/compression/compression_common.rb +59 -0
- data/spec/cql/compression/snappy_compressor_spec.rb +23 -0
- data/spec/cql/io/io_reactor_spec.rb +8 -1
- data/spec/cql/protocol/cql_protocol_handler_spec.rb +40 -0
- data/spec/cql/protocol/frame_decoder_spec.rb +132 -0
- data/spec/cql/protocol/frame_encoder_spec.rb +105 -0
- data/spec/cql/protocol/requests/credentials_request_spec.rb +2 -4
- data/spec/cql/protocol/requests/execute_request_spec.rb +5 -5
- data/spec/cql/protocol/requests/options_request_spec.rb +10 -4
- data/spec/cql/protocol/requests/prepare_request_spec.rb +3 -3
- data/spec/cql/protocol/requests/query_request_spec.rb +10 -5
- data/spec/cql/protocol/requests/register_request_spec.rb +3 -3
- data/spec/cql/protocol/requests/startup_request_spec.rb +11 -5
- data/spec/cql/protocol/responses/authenticate_response_spec.rb +27 -0
- data/spec/cql/protocol/responses/detailed_error_response_spec.rb +78 -0
- data/spec/cql/protocol/responses/error_response_spec.rb +36 -0
- data/spec/cql/protocol/responses/event_response_spec.rb +40 -0
- data/spec/cql/protocol/responses/prepared_result_response_spec.rb +108 -0
- data/spec/cql/protocol/responses/ready_response_spec.rb +39 -0
- data/spec/cql/protocol/responses/result_response_spec.rb +57 -0
- data/spec/cql/protocol/responses/rows_result_response_spec.rb +273 -0
- data/spec/cql/protocol/responses/schema_change_event_response_spec.rb +93 -0
- data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +51 -19
- data/spec/cql/protocol/responses/set_keyspace_result_response_spec.rb +34 -0
- data/spec/cql/protocol/responses/status_change_event_response_spec.rb +35 -0
- data/spec/cql/protocol/responses/supported_response_spec.rb +27 -0
- data/spec/cql/protocol/responses/topology_change_event_response_spec.rb +35 -0
- data/spec/cql/protocol/responses/void_result_response_spec.rb +29 -0
- data/spec/integration/client_spec.rb +45 -0
- data/spec/integration/protocol_spec.rb +46 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/fake_io_reactor.rb +1 -1
- metadata +51 -10
- data/lib/cql/protocol/response_frame.rb +0 -129
- data/spec/cql/protocol/request_spec.rb +0 -45
- data/spec/cql/protocol/response_frame_spec.rb +0 -811
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c27b19f205bb59c5f8fe37faa6259064d85c761
|
4
|
+
data.tar.gz: 74615d268c49624381e8c8088fb173834e3c0313
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e8bd6f3e31b0b6e201baca992267b12502e5b78b71ef64378d4f52b791a8a2036c049650c5c4e7f17a0a1b4814d942a423c802742e5173071430d59d1b811ab
|
7
|
+
data.tar.gz: 86539fa464d45531f30aea8198d70a726d20d6bf3247d2b25fe76d1e49a37b568c465772059af4adfd637a7371406f7410389ae824d592cd6b18c43bafcfff56
|
data/README.md
CHANGED
@@ -162,6 +162,19 @@ The default consistency level unless you've set it yourself is `:quorum`.
|
|
162
162
|
|
163
163
|
Consistency is ignored for `USE`, `TRUNCATE`, `CREATE` and `ALTER` statements, and some (like `:any`) aren't allowed in all situations.
|
164
164
|
|
165
|
+
## Compression
|
166
|
+
|
167
|
+
The CQL protocol supports frame compression, which can give you a performance boost if your requests or responses are big. To enable it you can pass a compressor object when you connect.
|
168
|
+
|
169
|
+
Cassandra currently supports two compression algorithms: Snappy and LZ4. Support for Snappy compression ships with cql-rb, but in order to use it you will have to install the [snappy](http://rubygems.org/gems/snappy) gem separately. Once it's installed you can enable compression like this:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
require 'cql/compression/snappy_compressor'
|
173
|
+
|
174
|
+
compressor = Cql::Compression::SnappyCompressor.new
|
175
|
+
client = Cql::Client.connect(hosts: %w[localhost], compressor: compressor)
|
176
|
+
```
|
177
|
+
|
165
178
|
# CQL3
|
166
179
|
|
167
180
|
This is just a driver for the Cassandra native CQL protocol, it doesn't really know anything about CQL. You can run any CQL3 statement and the driver will return whatever Cassandra replies with.
|
@@ -206,6 +219,10 @@ end
|
|
206
219
|
|
207
220
|
If your process does not fork and you still encounter deadlock errors, it might also be a bug. All IO is done is a dedicated thread, and if something happens that makes that thread shut down, Ruby will detect that the locks that the client code is waiting on can't be unlocked.
|
208
221
|
|
222
|
+
## I get "Bad file descriptor"
|
223
|
+
|
224
|
+
If you're using cql-rb on Windows there's an [experimental branch with Windows support](https://github.com/iconara/cql-rb/tree/windows_support). The problem is that Windows does not support non blocking reads on IO objects other than sockets, and the fix is very small. Unfortunately I have no way of properly testing things in Windows, so therefore the "experimental" label.
|
225
|
+
|
209
226
|
## I'm not getting all elements back from my list/set/map
|
210
227
|
|
211
228
|
There's a known issue with collections that get too big. The protocol uses a short for the size of collections, but there is no way for Cassandra to stop you from creating a collection bigger than 65536 elements, so when you do the size field overflows with strange results. The data is there, you just can't get it back.
|
@@ -232,9 +249,8 @@ Prereleases will be stable, in the sense that they will have finished and proper
|
|
232
249
|
|
233
250
|
# Known bugs & limitations
|
234
251
|
|
235
|
-
* No support for compression.
|
236
|
-
* No support for request tracing.
|
237
252
|
* JRuby 1.6 is not officially supported, although 1.6.8 should work, if you're stuck in JRuby 1.6.8 try and see if it works for you.
|
253
|
+
* Windows is not supported (there is experimental support in the [`windows` branch](https://github.com/iconara/cql-rb/tree/windows_support)).
|
238
254
|
* Large results are buffered in memory until the whole response has been loaded, the protocol makes it possible to start to deliver rows to the client code as soon as the metadata is loaded, but this is not supported yet.
|
239
255
|
* There is no cluster introspection utilities (like the `DESCRIBE` commands in `cqlsh`).
|
240
256
|
* New features in v2 of the protocol are not supported
|
@@ -243,15 +259,7 @@ Also check out the [issues](https://github.com/iconara/cql-rb/issues) for open b
|
|
243
259
|
|
244
260
|
# How to contribute
|
245
261
|
|
246
|
-
|
247
|
-
|
248
|
-
Follow the style of the existing code, make sure that existing tests pass, and that everything new has good test coverage. Put some effort into writing clear and concise commit messages, and write a good pull request description.
|
249
|
-
|
250
|
-
It takes time to understand other people's code, and even more time to understand a patch, so do as much as you can to make the maintainers' work easier. Be prepared for rejection, many times a feature is already planned, or the proposed design would be in the way of other planned features, or the maintainers' just feel that it will be faster to implement the features themselves than to try to integrate your patch.
|
251
|
-
|
252
|
-
Feel free to open a pull request before the feature is finished, that way you can have a conversation with the maintainers' during the development, and you can make adjustments to the design as you go along instead of having your whole feature rejected because of reasons such as those above. If you do, please make it clear that the pull request is a work in progress, or a request for comment.
|
253
|
-
|
254
|
-
Always remember that the maintainers' work on this project in their free time and that they don't work for you, or for your benefit. They have no obligation to do what you think is right -- but if you're nice they might anyway.
|
262
|
+
[See CONTRIBUTING.md](CONTRIBUTING.md)
|
255
263
|
|
256
264
|
# Copyright
|
257
265
|
|
data/lib/cql.rb
CHANGED
data/lib/cql/client.rb
CHANGED
@@ -6,12 +6,13 @@ module Cql
|
|
6
6
|
# if any. `message` contains the human readable error message sent by the
|
7
7
|
# server.
|
8
8
|
class QueryError < CqlError
|
9
|
-
attr_reader :code, :cql
|
9
|
+
attr_reader :code, :cql, :details
|
10
10
|
|
11
|
-
def initialize(code, message, cql=nil)
|
11
|
+
def initialize(code, message, cql=nil, details=nil)
|
12
12
|
super(message)
|
13
13
|
@code = code
|
14
14
|
@cql = cql
|
15
|
+
@details = details
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
@@ -19,6 +20,7 @@ module Cql
|
|
19
20
|
TimeoutError = Class.new(CqlError)
|
20
21
|
ClientError = Class.new(CqlError)
|
21
22
|
AuthenticationError = Class.new(ClientError)
|
23
|
+
IncompleteTraceError = Class.new(ClientError)
|
22
24
|
|
23
25
|
# A CQL client manages connections to one or more Cassandra nodes and you use
|
24
26
|
# it run queries, insert and update data.
|
@@ -88,6 +90,11 @@ module Cql
|
|
88
90
|
# @option options [Integer] :default_consistency (:quorum) The consistency
|
89
91
|
# to use unless otherwise specified. Consistency can also be specified on
|
90
92
|
# a per-request basis.
|
93
|
+
# @option options [Cql::Compression::Compressor] :compressor An object that
|
94
|
+
# can compress and decompress frames. By specifying this option frame
|
95
|
+
# compression will be enabled. If the server does not support compression
|
96
|
+
# or the specific compression algorithm specified by the compressor,
|
97
|
+
# compression will not be enabled and a warning will be logged.
|
91
98
|
# @option options [Integer] :logger If you want the client to log
|
92
99
|
# significant events pass an object implementing the standard Ruby logger
|
93
100
|
# interface (e.g. quacks like `Logger` from the standard library) with
|
@@ -142,7 +149,23 @@ module Cql
|
|
142
149
|
|
143
150
|
# @!method execute(cql, options_or_consistency=nil)
|
144
151
|
#
|
145
|
-
# Execute a CQL statement
|
152
|
+
# Execute a CQL statement.
|
153
|
+
#
|
154
|
+
# @example A simple CQL query
|
155
|
+
# result = client.execute("SELECT * FROM users WHERE user_name = 'sue'")
|
156
|
+
# result.each do |row|
|
157
|
+
# p row
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# @example Specifying the consistency as a symbol
|
161
|
+
# client.execute("UPDATE users SET full_name = 'Sue S. Smith' WHERE user_name = 'sue'", consistency: :one)
|
162
|
+
#
|
163
|
+
# @example Specifying the consistency and other options
|
164
|
+
# client.execute("SELECT * FROM users", consistency: :all, timeout: 1.5)
|
165
|
+
#
|
166
|
+
# @example Activating tracing for a query
|
167
|
+
# result = client.execute("SELECT * FROM users", tracing: true)
|
168
|
+
# p result.trace_id
|
146
169
|
#
|
147
170
|
# @param [String] cql
|
148
171
|
# @param [Hash] options_or_consistency Either a consistency as a symbol
|
@@ -153,14 +176,19 @@ module Cql
|
|
153
176
|
# @option options_or_consistency [Symbol] :timeout (nil) How long to wait
|
154
177
|
# for a response. If this timeout expires a {Cql::TimeoutError} will
|
155
178
|
# be raised.
|
179
|
+
# @option options_or_consistency [Symbol] :trace (false) Request tracing
|
180
|
+
# for this request. See {Cql::Client::QueryResult} and
|
181
|
+
# {Cql::Client::VoidResult} for how to retrieve the tracing data.
|
156
182
|
# @raise [Cql::NotConnectedError] raised when the client is not connected
|
157
183
|
# @raise [Cql::TimeoutError] raised when a timeout was specified and no
|
158
184
|
# response was received within the timeout.
|
159
185
|
# @raise [Cql::QueryError] raised when the CQL has syntax errors or for
|
160
186
|
# other situations when the server complains.
|
161
|
-
# @return [nil, Cql::Client::QueryResult]
|
162
|
-
# return `nil`, but `SELECT` statements
|
163
|
-
# (see {Cql::Client::QueryResult})
|
187
|
+
# @return [nil, Cql::Client::QueryResult, Cql::Client::VoidResult] Some
|
188
|
+
# queries have no result and return `nil`, but `SELECT` statements
|
189
|
+
# return an `Enumerable` of rows (see {Cql::Client::QueryResult}), and
|
190
|
+
# `INSERT` and `UPDATE` return a similar type
|
191
|
+
# (see {Cql::Client::VoidResult}).
|
164
192
|
|
165
193
|
# @!method prepare(cql)
|
166
194
|
#
|
@@ -206,9 +234,11 @@ module Cql
|
|
206
234
|
# @raise [Cql::Io::IoError] raised when there is an IO error, for example
|
207
235
|
# if the server suddenly closes the connection
|
208
236
|
# @raise [Cql::QueryError] raised when there is an error on the server side
|
209
|
-
# @return [nil, Cql::Client::QueryResult]
|
210
|
-
#
|
211
|
-
# rows (see {Cql::Client::QueryResult})
|
237
|
+
# @return [nil, Cql::Client::QueryResult, Cql::Client::VoidResult] Some
|
238
|
+
# queries have no result and return `nil`, but `SELECT` statements
|
239
|
+
# return an `Enumerable` of rows (see {Cql::Client::QueryResult}), and
|
240
|
+
# `INSERT` and `UPDATE` return a similar type
|
241
|
+
# (see {Cql::Client::VoidResult}).
|
212
242
|
def execute(*args)
|
213
243
|
end
|
214
244
|
end
|
@@ -221,6 +251,8 @@ require 'cql/client/null_logger'
|
|
221
251
|
require 'cql/client/column_metadata'
|
222
252
|
require 'cql/client/result_metadata'
|
223
253
|
require 'cql/client/query_result'
|
254
|
+
require 'cql/client/void_result'
|
255
|
+
require 'cql/client/query_trace'
|
224
256
|
require 'cql/client/execute_options_decoder'
|
225
257
|
require 'cql/client/keyspace_changer'
|
226
258
|
require 'cql/client/asynchronous_client'
|
@@ -5,8 +5,9 @@ module Cql
|
|
5
5
|
# @private
|
6
6
|
class AsynchronousClient < Client
|
7
7
|
def initialize(options={})
|
8
|
+
compressor = options[:compressor]
|
8
9
|
@logger = options[:logger] || NullLogger.new
|
9
|
-
@io_reactor = options[:io_reactor] || Io::IoReactor.new(
|
10
|
+
@io_reactor = options[:io_reactor] || Io::IoReactor.new(protocol_handler_factory(compressor))
|
10
11
|
@hosts = extract_hosts(options)
|
11
12
|
@initial_keyspace = options[:keyspace]
|
12
13
|
@lock = Mutex.new
|
@@ -22,7 +23,7 @@ module Cql
|
|
22
23
|
connection_timeout = options[:connection_timeout] || DEFAULT_CONNECTION_TIMEOUT
|
23
24
|
default_consistency = options[:default_consistency] || DEFAULT_CONSISTENCY
|
24
25
|
@execute_options_decoder = ExecuteOptionsDecoder.new(default_consistency)
|
25
|
-
@connection_helper = ConnectionHelper.new(@io_reactor, port, credentials, connections_per_node, connection_timeout, @logger)
|
26
|
+
@connection_helper = ConnectionHelper.new(@io_reactor, port, credentials, connections_per_node, connection_timeout, compressor, @logger)
|
26
27
|
end
|
27
28
|
|
28
29
|
def connect
|
@@ -85,8 +86,8 @@ module Cql
|
|
85
86
|
|
86
87
|
def execute(cql, options_or_consistency=nil)
|
87
88
|
with_failure_handler do
|
88
|
-
consistency, timeout = @execute_options_decoder.decode_options(options_or_consistency)
|
89
|
-
execute_request(Protocol::QueryRequest.new(cql, consistency), timeout)
|
89
|
+
consistency, timeout, trace = @execute_options_decoder.decode_options(options_or_consistency)
|
90
|
+
execute_request(Protocol::QueryRequest.new(cql, consistency, trace), timeout)
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
@@ -103,6 +104,10 @@ module Cql
|
|
103
104
|
DEFAULT_CONNECTION_TIMEOUT = 10
|
104
105
|
MAX_RECONNECTION_ATTEMPTS = 5
|
105
106
|
|
107
|
+
def protocol_handler_factory(compressor)
|
108
|
+
lambda { |connection, timeout| Protocol::CqlProtocolHandler.new(connection, timeout, compressor) }
|
109
|
+
end
|
110
|
+
|
106
111
|
def extract_hosts(options)
|
107
112
|
if options[:hosts]
|
108
113
|
options[:hosts].uniq
|
@@ -60,9 +60,9 @@ module Cql
|
|
60
60
|
unless bound_args.size == @raw_metadata.size && args.size <= 1
|
61
61
|
raise ArgumentError, "Expected #{@raw_metadata.size} arguments, got #{bound_args.size}"
|
62
62
|
end
|
63
|
-
consistency, timeout = @execute_options_decoder.decode_options(args.last)
|
63
|
+
consistency, timeout, trace = @execute_options_decoder.decode_options(args.last)
|
64
64
|
statement_id = connection[self]
|
65
|
-
request = Protocol::ExecuteRequest.new(statement_id, @raw_metadata, bound_args, consistency)
|
65
|
+
request = Protocol::ExecuteRequest.new(statement_id, @raw_metadata, bound_args, consistency, trace)
|
66
66
|
@request_runner.execute(connection, request, timeout)
|
67
67
|
end
|
68
68
|
end
|
@@ -4,7 +4,7 @@ module Cql
|
|
4
4
|
module Client
|
5
5
|
# @private
|
6
6
|
class ConnectionHelper
|
7
|
-
def initialize(io_reactor, port, credentials, connections_per_node, connection_timeout, logger)
|
7
|
+
def initialize(io_reactor, port, credentials, connections_per_node, connection_timeout, compressor, logger)
|
8
8
|
@io_reactor = io_reactor
|
9
9
|
@port = port
|
10
10
|
@credentials = credentials
|
@@ -13,6 +13,7 @@ module Cql
|
|
13
13
|
@logger = logger
|
14
14
|
@request_runner = RequestRunner.new
|
15
15
|
@keyspace_changer = KeyspaceChanger.new
|
16
|
+
@compressor = compressor
|
16
17
|
end
|
17
18
|
|
18
19
|
def connect(hosts, initial_keyspace)
|
@@ -100,18 +101,50 @@ module Cql
|
|
100
101
|
end
|
101
102
|
|
102
103
|
def connect_to_host(host, keyspace)
|
103
|
-
|
104
|
+
if @compressor
|
105
|
+
@logger.debug('Connecting to node at %s:%d using "%s" compression' % [host, @port, @compressor.algorithm])
|
106
|
+
else
|
107
|
+
@logger.debug('Connecting to node at %s:%d' % [host, @port])
|
108
|
+
end
|
104
109
|
connected = @io_reactor.connect(host, @port, @connection_timeout)
|
105
110
|
connected.flat_map do |connection|
|
106
|
-
|
111
|
+
f = cache_supported_options(connection)
|
112
|
+
f = f.flat_map { send_startup_request(connection) }
|
113
|
+
f = f.flat_map { |response| maybe_authenticate(response, connection) }
|
114
|
+
f = f.flat_map { identify_node(connection) }
|
115
|
+
f = f.flat_map { change_keyspace(keyspace, connection) }
|
116
|
+
f
|
107
117
|
end
|
108
118
|
end
|
109
119
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
120
|
+
def cache_supported_options(connection)
|
121
|
+
f = @request_runner.execute(connection, Protocol::OptionsRequest.new)
|
122
|
+
f.on_value do |supported_options|
|
123
|
+
connection[:cql_version] = supported_options['CQL_VERSION']
|
124
|
+
connection[:compression] = supported_options['COMPRESSION']
|
125
|
+
end
|
126
|
+
f
|
127
|
+
end
|
128
|
+
|
129
|
+
def send_startup_request(connection)
|
130
|
+
compression = @compressor && @compressor.algorithm
|
131
|
+
if @compressor && !connection[:compression].include?(@compressor.algorithm)
|
132
|
+
@logger.warn(%[Compression algorithm "#{@compressor.algorithm}" not supported (server supports "#{connection[:compression].join('", "')}")])
|
133
|
+
compression = nil
|
134
|
+
end
|
135
|
+
request = Protocol::StartupRequest.new(nil, compression)
|
136
|
+
@request_runner.execute(connection, request)
|
137
|
+
end
|
138
|
+
|
139
|
+
def maybe_authenticate(response, connection)
|
140
|
+
return Future.resolved(connection) unless response.is_a?(AuthenticationRequired)
|
141
|
+
return Future.failed(AuthenticationError.new('Server requested authentication, but no credentials given')) unless @credentials
|
142
|
+
send_credentials(@credentials, connection)
|
143
|
+
end
|
144
|
+
|
145
|
+
def send_credentials(credentials, connection)
|
146
|
+
credentials_request = Protocol::CredentialsRequest.new(credentials)
|
147
|
+
@request_runner.execute(connection, credentials_request)
|
115
148
|
end
|
116
149
|
|
117
150
|
def identify_node(connection)
|
@@ -126,18 +159,8 @@ module Cql
|
|
126
159
|
f
|
127
160
|
end
|
128
161
|
|
129
|
-
def
|
130
|
-
|
131
|
-
when AuthenticationRequired
|
132
|
-
if @credentials
|
133
|
-
credentials_request = Protocol::CredentialsRequest.new(@credentials)
|
134
|
-
@request_runner.execute(connection, credentials_request).map { connection }
|
135
|
-
else
|
136
|
-
Future.failed(AuthenticationError.new('Server requested authentication, but no credentials given'))
|
137
|
-
end
|
138
|
-
else
|
139
|
-
Future.resolved(connection)
|
140
|
-
end
|
162
|
+
def change_keyspace(keyspace, connection)
|
163
|
+
@keyspace_changer.use_keyspace(keyspace, connection)
|
141
164
|
end
|
142
165
|
|
143
166
|
class FailedConnection
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Cql
|
4
4
|
module Client
|
5
|
+
# @private
|
5
6
|
class ExecuteOptionsDecoder
|
6
7
|
def initialize(default_consistency)
|
7
8
|
@default_consistency = default_consistency
|
@@ -10,14 +11,16 @@ module Cql
|
|
10
11
|
def decode_options(options_or_consistency)
|
11
12
|
consistency = @default_consistency
|
12
13
|
timeout = nil
|
14
|
+
trace = false
|
13
15
|
case options_or_consistency
|
14
16
|
when Symbol
|
15
17
|
consistency = options_or_consistency
|
16
18
|
when Hash
|
17
19
|
consistency = options_or_consistency[:consistency] || consistency
|
18
20
|
timeout = options_or_consistency[:timeout]
|
21
|
+
trace = options_or_consistency[:trace]
|
19
22
|
end
|
20
|
-
return consistency, timeout
|
23
|
+
return consistency, timeout, trace
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
@@ -8,14 +8,19 @@ module Cql
|
|
8
8
|
# @return [ResultMetadata]
|
9
9
|
attr_reader :metadata
|
10
10
|
|
11
|
+
# The ID of the query trace associated with the query, if any.
|
12
|
+
#
|
13
|
+
# @return [Cql::Uuid]
|
14
|
+
attr_reader :trace_id
|
15
|
+
|
11
16
|
# @private
|
12
|
-
def initialize(metadata, rows)
|
17
|
+
def initialize(metadata, rows, trace_id)
|
13
18
|
@metadata = ResultMetadata.new(metadata)
|
14
19
|
@rows = rows
|
20
|
+
@trace_id = trace_id
|
15
21
|
end
|
16
22
|
|
17
23
|
# Returns whether or not there are any rows in this result set
|
18
|
-
#
|
19
24
|
def empty?
|
20
25
|
@rows.empty?
|
21
26
|
end
|
@@ -24,7 +29,6 @@ module Cql
|
|
24
29
|
#
|
25
30
|
# @yieldparam [Hash] row each row in the result set as a hash
|
26
31
|
# @return [Enumerable<Hash>]
|
27
|
-
#
|
28
32
|
def each(&block)
|
29
33
|
@rows.each(&block)
|
30
34
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Client
|
5
|
+
# @private
|
6
|
+
class QueryTrace
|
7
|
+
attr_reader :coordinator, :cql, :started_at, :duration, :events
|
8
|
+
|
9
|
+
# @private
|
10
|
+
def initialize(session, events)
|
11
|
+
if session
|
12
|
+
raise IncompleteTraceError, 'Trace incomplete, try loading it again' unless session['duration']
|
13
|
+
@coordinator = session['coordinator']
|
14
|
+
@cql = (parameters = session['parameters']) && parameters['query']
|
15
|
+
@started_at = session['started_at']
|
16
|
+
@duration = session['duration']/1_000_000.0
|
17
|
+
if events
|
18
|
+
@events = events.map { |e| TraceEvent.new(e) }.freeze
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@events = [].freeze
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @private
|
27
|
+
class TraceEvent
|
28
|
+
attr_reader :activity, :source, :source_elapsed, :time
|
29
|
+
|
30
|
+
# @private
|
31
|
+
def initialize(event)
|
32
|
+
@activity = event['activity']
|
33
|
+
@source = event['source']
|
34
|
+
@source_elapsed = event['source_elapsed']/1_000_000.0
|
35
|
+
@time = event['event_id'].to_time
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @private
|
40
|
+
class NullQueryTrace < QueryTrace
|
41
|
+
def initialize
|
42
|
+
super(nil, nil)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -8,14 +8,19 @@ module Cql
|
|
8
8
|
connection.send_request(request, timeout).map do |response|
|
9
9
|
case response
|
10
10
|
when Protocol::RowsResultResponse
|
11
|
-
QueryResult.new(response.metadata, response.rows)
|
11
|
+
QueryResult.new(response.metadata, response.rows, response.trace_id)
|
12
|
+
when Protocol::VoidResultResponse
|
13
|
+
response.trace_id ? VoidResult.new(response.trace_id) : VoidResult::INSTANCE
|
12
14
|
when Protocol::ErrorResponse
|
13
15
|
cql = request.is_a?(Protocol::QueryRequest) ? request.cql : nil
|
14
|
-
|
16
|
+
details = response.respond_to?(:details) ? response.details : nil
|
17
|
+
raise QueryError.new(response.code, response.message, cql, details)
|
15
18
|
when Protocol::SetKeyspaceResultResponse
|
16
19
|
KeyspaceChanged.new(response.keyspace)
|
17
20
|
when Protocol::AuthenticateResponse
|
18
21
|
AuthenticationRequired.new(response.authentication_class)
|
22
|
+
when Protocol::SupportedResponse
|
23
|
+
response.options
|
19
24
|
else
|
20
25
|
if block_given?
|
21
26
|
yield response
|