cassandra-driver 3.0.0 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +22 -20
- data/lib/cassandra.rb +35 -25
- data/lib/cassandra/auth.rb +3 -1
- data/lib/cassandra/cluster/client.rb +38 -32
- data/lib/cassandra/cluster/connector.rb +7 -9
- data/lib/cassandra/cluster/options.rb +18 -4
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +3 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1 -1
- data/lib/cassandra/custom_data.rb +51 -0
- data/lib/cassandra/driver.rb +21 -17
- data/lib/cassandra/execution/options.rb +1 -1
- data/lib/cassandra/protocol.rb +7 -0
- data/lib/cassandra/protocol/coder.rb +28 -8
- data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +3 -2
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +4 -2
- data/lib/cassandra/protocol/v1.rb +2 -1
- data/lib/cassandra/protocol/v3.rb +2 -1
- data/lib/cassandra/protocol/v4.rb +5 -3
- data/lib/cassandra/result.rb +2 -2
- data/lib/cassandra/session.rb +7 -14
- data/lib/cassandra/statement.rb +5 -0
- data/lib/cassandra/statements/batch.rb +6 -0
- data/lib/cassandra/statements/bound.rb +5 -0
- data/lib/cassandra/statements/prepared.rb +11 -2
- data/lib/cassandra/statements/simple.rb +5 -0
- data/lib/cassandra/statements/void.rb +5 -0
- data/lib/cassandra/tuple.rb +2 -2
- data/lib/cassandra/types.rb +2 -2
- data/lib/cassandra/util.rb +1 -0
- data/lib/cassandra/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MjRlMWI4NGUyYzNjNzMzZTQ1MTNiNDE4NTIxODk3NGIwOTIwZjVkZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YWMwYmNlM2RmYzIzYWY5MGQ2MmIyNjU5NTU3NTkyNGMxYmY0NTAyNA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NTdhMWZiODYzYTViZGJiNTY5NDYzMjQ2ZDZiMDE2MTY4MTI3NTY3NjM0Y2Rl
|
10
|
+
YmE0MjkxYmZhNDI0OTliMDcyZWUyMjM3M2E2OWIzNzg2MGJkODVlMjhmYmQ3
|
11
|
+
N2NhYzQ5NmY2MmQxYzdkY2U3NTJmZDAyMjI2MWE4MTM3YTZkMmY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Y2IwOGMwOGQzYTlkZjUzYjQ1NzFlZjJhNTY3YWM2MmNjN2QxM2ExZmU0YWZh
|
14
|
+
ODBjYjQ4ODUwZDAzMTZjMzRhMDEwYzhkZDA4Zjk3NjIzOWI1OWM2ZGViYjQ0
|
15
|
+
ZjZkZjM0YTEzNTY0YTAxNzA0YWEwYjdlOWY2NjkyOWNkZDE4YjM=
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Datastax Ruby Driver for Apache Cassandra
|
2
2
|
|
3
|
-
*If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for latest version through ruby driver docs](http://datastax.
|
3
|
+
*If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for the latest version through ruby driver docs](http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html) or via the release tags, [e.g. v3.0.2](https://github.com/datastax/ruby-driver/tree/v3.0.2).*
|
4
4
|
|
5
5
|
[![Build Status](https://travis-ci.org/datastax/ruby-driver.svg?branch=master)](https://travis-ci.org/datastax/ruby-driver)
|
6
6
|
|
@@ -8,7 +8,7 @@ A Ruby client driver for Apache Cassandra. This driver works exclusively with
|
|
8
8
|
the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
9
9
|
|
10
10
|
- Code: https://github.com/datastax/ruby-driver
|
11
|
-
- Docs: http://datastax.
|
11
|
+
- Docs: http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html
|
12
12
|
- Jira: https://datastax-oss.atlassian.net/browse/RUBY
|
13
13
|
- Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
|
14
14
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
@@ -16,14 +16,14 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
16
16
|
|
17
17
|
This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we added support for:
|
18
18
|
|
19
|
-
* [Asynchronous execution](http://datastax.
|
20
|
-
* One-off, [prepared](http://datastax.
|
21
|
-
* Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax.
|
22
|
-
* Various [load-balancing](http://datastax.
|
23
|
-
* [SSL encryption](http://datastax.
|
24
|
-
* [Flexible and robust error handling](http://datastax.
|
25
|
-
* [Per-request execution information and tracing](http://datastax.
|
26
|
-
* [Configurable address resolution](http://datastax.
|
19
|
+
* [Asynchronous execution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/asynchronous_io/)
|
20
|
+
* One-off, [prepared](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/prepared_statements/) and [batch statements](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/batch_statements/)
|
21
|
+
* Automatic peer discovery and cluster metadata with [support for change notifications](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/state_listeners/)
|
22
|
+
* Various [load-balancing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/), [retry](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/retry_policies/) and [reconnection](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/reconnection/) policies with [ability to write your own](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/implementing_a_policy/)
|
23
|
+
* [SSL encryption](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/security/ssl_encryption/)
|
24
|
+
* [Flexible and robust error handling](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/error_handling/)
|
25
|
+
* [Per-request execution information and tracing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/debugging/)
|
26
|
+
* [Configurable address resolution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/address_resolution/)
|
27
27
|
|
28
28
|
[Check out the slides from Ruby Driver Explained](https://speakerdeck.com/avalanche123/ruby-driver-explained) for a detailed overview of the Ruby Driver architecture.
|
29
29
|
|
@@ -67,9 +67,9 @@ __Note__: The host you specify is just a seed node, the driver will automaticall
|
|
67
67
|
|
68
68
|
Read more:
|
69
69
|
|
70
|
-
* [`Cassandra.cluster` options](http://datastax.
|
71
|
-
* [`Session#execute_async` options](http://datastax.
|
72
|
-
* [Usage documentation](http://datastax.
|
70
|
+
* [`Cassandra.cluster` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/#cluster-class_method)
|
71
|
+
* [`Session#execute_async` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/session/#execute_async-instance_method)
|
72
|
+
* [Usage documentation](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features)
|
73
73
|
|
74
74
|
## Installation
|
75
75
|
|
@@ -85,14 +85,16 @@ Install via Gemfile
|
|
85
85
|
gem 'cassandra-driver'
|
86
86
|
```
|
87
87
|
|
88
|
-
__Note__: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://datastax.
|
88
|
+
__Note__: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/#compression)
|
89
89
|
|
90
90
|
|
91
91
|
## Upgrading from cql-rb
|
92
92
|
|
93
|
-
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/
|
93
|
+
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/v3.0.2/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
|
94
94
|
|
95
|
-
## What's new in v3.0
|
95
|
+
## What's new in v3.0
|
96
|
+
|
97
|
+
See the [changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md) for details on patch versions.
|
96
98
|
|
97
99
|
### Features:
|
98
100
|
|
@@ -162,7 +164,7 @@ examples in the `features/` directory.
|
|
162
164
|
## Running tests
|
163
165
|
|
164
166
|
If you don't feel like reading through the following instructions on how to run
|
165
|
-
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/
|
167
|
+
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/v3.0.2/.travis.yml).
|
166
168
|
|
167
169
|
* Check out the driver codebase and install test dependencies:
|
168
170
|
|
@@ -186,7 +188,7 @@ CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration
|
|
186
188
|
## Changelog & versioning
|
187
189
|
|
188
190
|
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
189
|
-
[changelog](https://github.com/datastax/ruby-driver/blob/
|
191
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md). Version
|
190
192
|
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
191
193
|
|
192
194
|
Private and experimental APIs, defined as whatever is not in the
|
@@ -210,7 +212,7 @@ the release.
|
|
210
212
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
211
213
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
212
214
|
|
213
|
-
Please [refer to the usage documentation for more information on common pitfalls](http://datastax.
|
215
|
+
Please [refer to the usage documentation for more information on common pitfalls](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/)
|
214
216
|
|
215
217
|
## Contributing
|
216
218
|
|
@@ -240,4 +242,4 @@ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
|
240
242
|
either express or implied. See the License for the specific language governing permissions
|
241
243
|
and limitations under the License.
|
242
244
|
|
243
|
-
[1]: http://datastax.
|
245
|
+
[1]: http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api
|
data/lib/cassandra.rb
CHANGED
@@ -66,6 +66,7 @@ module Cassandra
|
|
66
66
|
:connections_per_remote_node,
|
67
67
|
:consistency,
|
68
68
|
:credentials,
|
69
|
+
:custom_types,
|
69
70
|
:datacenter,
|
70
71
|
:futures_factory,
|
71
72
|
:heartbeat_interval,
|
@@ -293,28 +294,7 @@ module Cassandra
|
|
293
294
|
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
294
295
|
# cluster instance.
|
295
296
|
def self.cluster_async(options = {})
|
296
|
-
options = validate_and_massage_options(options)
|
297
|
-
hosts = []
|
298
|
-
|
299
|
-
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
300
|
-
case host
|
301
|
-
when ::IPAddr
|
302
|
-
hosts << host
|
303
|
-
when ::String # ip address or hostname
|
304
|
-
Resolv.each_address(host) do |ip|
|
305
|
-
hosts << ::IPAddr.new(ip)
|
306
|
-
end
|
307
|
-
else
|
308
|
-
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
if hosts.empty?
|
313
|
-
raise ::ArgumentError,
|
314
|
-
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
315
|
-
end
|
316
|
-
|
317
|
-
hosts.shuffle!
|
297
|
+
options, hosts = validate_and_massage_options(options)
|
318
298
|
rescue => e
|
319
299
|
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
320
300
|
futures.error(e)
|
@@ -664,14 +644,14 @@ module Cassandra
|
|
664
644
|
|
665
645
|
case address_resolution
|
666
646
|
when :none
|
667
|
-
|
647
|
+
# do nothing
|
668
648
|
when :ec2_multi_region
|
669
649
|
options[:address_resolution_policy] =
|
670
650
|
AddressResolution::Policies::EC2MultiRegion.new
|
671
651
|
else
|
672
652
|
raise ::ArgumentError,
|
673
653
|
':address_resolution must be either :none or :ec2_multi_region, ' \
|
674
|
-
|
654
|
+
"#{address_resolution.inspect} given"
|
675
655
|
end
|
676
656
|
end
|
677
657
|
|
@@ -757,7 +737,31 @@ module Cassandra
|
|
757
737
|
end
|
758
738
|
end
|
759
739
|
end
|
760
|
-
|
740
|
+
|
741
|
+
# Get host addresses.
|
742
|
+
hosts = []
|
743
|
+
|
744
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
745
|
+
case host
|
746
|
+
when ::IPAddr
|
747
|
+
hosts << host
|
748
|
+
when ::String # ip address or hostname
|
749
|
+
Resolv.each_address(host) do |ip|
|
750
|
+
hosts << ::IPAddr.new(ip)
|
751
|
+
end
|
752
|
+
else
|
753
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
if hosts.empty?
|
758
|
+
raise ::ArgumentError,
|
759
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
760
|
+
end
|
761
|
+
|
762
|
+
hosts.shuffle!
|
763
|
+
|
764
|
+
[options, hosts]
|
761
765
|
end
|
762
766
|
|
763
767
|
# @private
|
@@ -798,6 +802,7 @@ require 'cassandra/null_logger'
|
|
798
802
|
require 'cassandra/executors'
|
799
803
|
require 'cassandra/future'
|
800
804
|
require 'cassandra/cluster'
|
805
|
+
require 'cassandra/custom_data'
|
801
806
|
require 'cassandra/driver'
|
802
807
|
require 'cassandra/host'
|
803
808
|
require 'cassandra/session'
|
@@ -831,6 +836,11 @@ require 'cassandra/util'
|
|
831
836
|
# murmur3 hash extension
|
832
837
|
require 'cassandra_murmur3'
|
833
838
|
|
839
|
+
# SortedSet has a race condition where it does some class/global initialization when the first instance is created.
|
840
|
+
# If this is done in a multi-threaded environment, bad things can happen. So force the initialization here,
|
841
|
+
# when loading the C* module.
|
842
|
+
::SortedSet.new
|
843
|
+
|
834
844
|
module Cassandra
|
835
845
|
# @private
|
836
846
|
VOID_STATEMENT = Statements::Void.new
|
data/lib/cassandra/auth.rb
CHANGED
@@ -34,7 +34,7 @@ module Cassandra
|
|
34
34
|
#
|
35
35
|
# @see Cassandra::Auth::Providers
|
36
36
|
class Provider
|
37
|
-
# @!method create_authenticator(authentication_class,
|
37
|
+
# @!method create_authenticator(authentication_class, host)
|
38
38
|
#
|
39
39
|
# Create a new authenticator object. This method will be called once per
|
40
40
|
# connection that requires authentication. The auth provider can create
|
@@ -45,6 +45,8 @@ module Cassandra
|
|
45
45
|
#
|
46
46
|
# @param authentication_class [String] the authentication class used by
|
47
47
|
# the server.
|
48
|
+
# @param host [Cassandra::Host] the node to whom we're authenticating.
|
49
|
+
#
|
48
50
|
# @return [Cassandra::Auth::Authenticator, nil] an object with an
|
49
51
|
# interface matching {Cassandra::Auth::Authenticator} or `nil` if the
|
50
52
|
# authentication class is not supported.
|
@@ -1390,38 +1390,44 @@ module Cassandra
|
|
1390
1390
|
end
|
1391
1391
|
else
|
1392
1392
|
response_future.on_failure do |ex|
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1393
|
+
if ex.is_a?(Errors::HostError) ||
|
1394
|
+
(ex.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
1395
|
+
|
1396
|
+
errors[host] = ex
|
1397
|
+
case request
|
1398
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1399
|
+
send_request_by_plan(promise,
|
1400
|
+
keyspace,
|
1401
|
+
statement,
|
1402
|
+
options,
|
1403
|
+
request,
|
1404
|
+
plan,
|
1405
|
+
timeout,
|
1406
|
+
errors,
|
1407
|
+
hosts)
|
1408
|
+
when Protocol::ExecuteRequest
|
1409
|
+
execute_by_plan(promise,
|
1410
|
+
keyspace,
|
1411
|
+
statement,
|
1412
|
+
options,
|
1413
|
+
request,
|
1414
|
+
plan,
|
1415
|
+
timeout,
|
1416
|
+
errors,
|
1417
|
+
hosts)
|
1418
|
+
when Protocol::BatchRequest
|
1419
|
+
batch_by_plan(promise,
|
1420
|
+
keyspace,
|
1421
|
+
statement,
|
1422
|
+
options,
|
1423
|
+
request,
|
1424
|
+
plan,
|
1425
|
+
timeout,
|
1426
|
+
errors,
|
1427
|
+
hosts)
|
1428
|
+
else
|
1429
|
+
promise.break(ex)
|
1430
|
+
end
|
1425
1431
|
else
|
1426
1432
|
promise.break(ex)
|
1427
1433
|
end
|
@@ -134,7 +134,8 @@ module Cassandra
|
|
134
134
|
@connection_options.compressor,
|
135
135
|
@connection_options.heartbeat_interval,
|
136
136
|
@connection_options.idle_timeout,
|
137
|
-
@connection_options.requests_per_connection
|
137
|
+
@connection_options.requests_per_connection,
|
138
|
+
@connection_options.custom_type_handlers)
|
138
139
|
end.flat_map do |connection|
|
139
140
|
# connection is a CqlProtocolHandler
|
140
141
|
f = request_options(connection)
|
@@ -154,7 +155,7 @@ module Cassandra
|
|
154
155
|
supported_cql_versions.first :
|
155
156
|
'3.1.0'
|
156
157
|
|
157
|
-
startup_connection(connection, cql_version, compression)
|
158
|
+
startup_connection(host, connection, cql_version, compression)
|
158
159
|
end
|
159
160
|
f.fallback do |error|
|
160
161
|
case error
|
@@ -200,7 +201,7 @@ module Cassandra
|
|
200
201
|
end
|
201
202
|
end
|
202
203
|
|
203
|
-
def startup_connection(connection, cql_version, compression)
|
204
|
+
def startup_connection(host, connection, cql_version, compression)
|
204
205
|
connection.send_request(Protocol::StartupRequest.new(cql_version, compression),
|
205
206
|
@execution_options.timeout).flat_map do |r|
|
206
207
|
case r
|
@@ -213,12 +214,9 @@ module Cassandra
|
|
213
214
|
Ione::Future.failed(cannot_authenticate_error)
|
214
215
|
end
|
215
216
|
else
|
216
|
-
authenticator = @connection_options.create_authenticator(
|
217
|
-
r.authentication_class)
|
217
|
+
authenticator = @connection_options.create_authenticator(r.authentication_class, host)
|
218
218
|
if authenticator
|
219
|
-
challenge_response_cycle(connection,
|
220
|
-
authenticator,
|
221
|
-
authenticator.initial_response)
|
219
|
+
challenge_response_cycle(connection, authenticator, authenticator.initial_response)
|
222
220
|
else
|
223
221
|
Ione::Future.failed(cannot_authenticate_error)
|
224
222
|
end
|
@@ -283,7 +281,7 @@ module Cassandra
|
|
283
281
|
case r
|
284
282
|
when Protocol::AuthChallengeResponse
|
285
283
|
token = authenticator.challenge_response(r.token)
|
286
|
-
challenge_response_cycle(
|
284
|
+
challenge_response_cycle(connection, authenticator, token)
|
287
285
|
when Protocol::AuthSuccessResponse
|
288
286
|
begin
|
289
287
|
authenticator.authentication_successful(r.token)
|
@@ -24,7 +24,7 @@ module Cassandra
|
|
24
24
|
|
25
25
|
attr_reader :auth_provider, :compressor, :connect_timeout, :credentials,
|
26
26
|
:heartbeat_interval, :idle_timeout, :port, :schema_refresh_delay,
|
27
|
-
:schema_refresh_timeout, :ssl
|
27
|
+
:schema_refresh_timeout, :ssl, :custom_type_handlers
|
28
28
|
attr_boolean :protocol_negotiable, :synchronize_schema, :nodelay
|
29
29
|
|
30
30
|
attr_accessor :protocol_version
|
@@ -45,7 +45,8 @@ module Cassandra
|
|
45
45
|
schema_refresh_delay,
|
46
46
|
schema_refresh_timeout,
|
47
47
|
nodelay,
|
48
|
-
requests_per_connection
|
48
|
+
requests_per_connection,
|
49
|
+
custom_types)
|
49
50
|
@logger = logger
|
50
51
|
@protocol_version = protocol_version
|
51
52
|
@credentials = credentials
|
@@ -60,6 +61,10 @@ module Cassandra
|
|
60
61
|
@schema_refresh_delay = schema_refresh_delay
|
61
62
|
@schema_refresh_timeout = schema_refresh_timeout
|
62
63
|
@nodelay = nodelay
|
64
|
+
@custom_type_handlers = {}
|
65
|
+
custom_types.each do |type_klass|
|
66
|
+
@custom_type_handlers[type_klass.type] = type_klass
|
67
|
+
end
|
63
68
|
|
64
69
|
@connections_per_local_node = connections_per_local_node
|
65
70
|
@connections_per_remote_node = connections_per_remote_node
|
@@ -78,8 +83,17 @@ module Cassandra
|
|
78
83
|
@compressor && @compressor.algorithm
|
79
84
|
end
|
80
85
|
|
81
|
-
def create_authenticator(authentication_class)
|
82
|
-
|
86
|
+
def create_authenticator(authentication_class, host)
|
87
|
+
if @auth_provider
|
88
|
+
# Auth providers should take an auth-class and host, but they used to not, so for backward compatibility
|
89
|
+
# we figure out if this provider does, and if so send both args, otherwise just send the auth-class.
|
90
|
+
|
91
|
+
if @auth_provider.method(:create_authenticator).arity == 1
|
92
|
+
@auth_provider.create_authenticator(authentication_class)
|
93
|
+
else
|
94
|
+
@auth_provider.create_authenticator(authentication_class, host)
|
95
|
+
end
|
96
|
+
end
|
83
97
|
end
|
84
98
|
|
85
99
|
def connections_per_local_node
|
@@ -72,6 +72,9 @@ module Cassandra
|
|
72
72
|
Cassandra::Types.tuple(*node.children.map { |t| lookup_type(t, types)})
|
73
73
|
when 'empty' then
|
74
74
|
Cassandra::Types.custom('org.apache.cassandra.db.marshal.EmptyType')
|
75
|
+
when /\A'/ then
|
76
|
+
# Custom type.
|
77
|
+
Cassandra::Types.custom(node.name[1..-2])
|
75
78
|
else
|
76
79
|
types.fetch(node.name) do
|
77
80
|
raise IncompleteTypeError, "unable to lookup type #{node.name.inspect}"
|
@@ -836,7 +836,7 @@ module Cassandra
|
|
836
836
|
initial_state = Util.encode_object(
|
837
837
|
Protocol::Coder.read_value_v4(
|
838
838
|
Protocol::CqlByteBuffer.new.append_bytes(aggregate_data['initcond']),
|
839
|
-
state_type))
|
839
|
+
state_type, nil))
|
840
840
|
|
841
841
|
# The state-function takes arguments: first the stype, then the args of the aggregate.
|
842
842
|
state_function = functions.get(aggregate_data['state_func'],
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
# Use this module to mark domain object classes as custom type implementations for custom-type
|
20
|
+
# columns in C*. This module has no logic of its own, but indicates that the marked class has
|
21
|
+
# certain methods.
|
22
|
+
# @private
|
23
|
+
module Cassandra::CustomData
|
24
|
+
def self.included base
|
25
|
+
base.send :include, InstanceMethods
|
26
|
+
base.extend ClassMethods
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
# @return [Cassandra::Types::Custom] the custom type that this class represents.
|
31
|
+
def type
|
32
|
+
raise NotImplementedError, "#{self.class} must implement the :type class method"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Deserialize the given data into an instance of this domain object class.
|
36
|
+
# @param data [String] byte-array representation of a column value of this custom type.
|
37
|
+
# @return An instance of the domain object class.
|
38
|
+
# @raise [Cassandra::Errors::DecodingError] upon failure.
|
39
|
+
def deserialize(data)
|
40
|
+
raise NotImplementedError, "#{self.class} must implement the :deserialize class method"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
# Serialize this domain object into a byte array to send to C*.
|
46
|
+
# @return [String] byte-array representation of this domain object.
|
47
|
+
def serialize
|
48
|
+
raise NotImplementedError, "#{self.class} must implement the :serialize instance method"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/cassandra/driver.rb
CHANGED
@@ -92,23 +92,25 @@ module Cassandra
|
|
92
92
|
schema_fetcher)
|
93
93
|
end
|
94
94
|
|
95
|
+
let(:cluster_klass) { Cluster }
|
96
|
+
|
95
97
|
let(:cluster) do
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
98
|
+
cluster_klass.new(logger,
|
99
|
+
io_reactor,
|
100
|
+
executor,
|
101
|
+
control_connection,
|
102
|
+
cluster_registry,
|
103
|
+
cluster_schema,
|
104
|
+
cluster_metadata,
|
105
|
+
execution_options,
|
106
|
+
connection_options,
|
107
|
+
load_balancing_policy,
|
108
|
+
reconnection_policy,
|
109
|
+
retry_policy,
|
110
|
+
address_resolution_policy,
|
111
|
+
connector,
|
112
|
+
futures_factory,
|
113
|
+
timestamp_generator)
|
112
114
|
end
|
113
115
|
|
114
116
|
let(:execution_options) do
|
@@ -137,10 +139,12 @@ module Cassandra
|
|
137
139
|
schema_refresh_delay,
|
138
140
|
schema_refresh_timeout,
|
139
141
|
nodelay,
|
140
|
-
requests_per_connection
|
142
|
+
requests_per_connection,
|
143
|
+
custom_types
|
141
144
|
)
|
142
145
|
end
|
143
146
|
|
147
|
+
let(:custom_types) { [] }
|
144
148
|
let(:port) { 9042 }
|
145
149
|
let(:protocol_version) { nil }
|
146
150
|
let(:connect_timeout) { 10 }
|
@@ -177,7 +177,7 @@ module Cassandra
|
|
177
177
|
@consistency = consistency || trusted_options.consistency
|
178
178
|
@page_size = page_size || trusted_options.page_size
|
179
179
|
@trace = trace.nil? ? trusted_options.trace? : !!trace
|
180
|
-
@timeout = timeout
|
180
|
+
@timeout = options.key?(:timeout) ? timeout : trusted_options.timeout
|
181
181
|
@serial_consistency = serial_consistency || trusted_options.serial_consistency
|
182
182
|
@arguments = arguments || trusted_options.arguments
|
183
183
|
@type_hints = type_hints || trusted_options.type_hints
|
data/lib/cassandra/protocol.rb
CHANGED
@@ -28,6 +28,13 @@ module Cassandra
|
|
28
28
|
|
29
29
|
BYTES_FORMAT = 'C*'.freeze
|
30
30
|
TWO_INTS_FORMAT = 'NN'.freeze
|
31
|
+
|
32
|
+
# All of the formats above are big-endian (e.g. network-byte-order). Some payloads (custom types) may have
|
33
|
+
# little-endian components.
|
34
|
+
|
35
|
+
DOUBLE_FORMAT_LE = 'E'.freeze
|
36
|
+
INT_FORMAT_LE = 'V'.freeze
|
37
|
+
SHORT_FORMAT_LE = 'v'.freeze
|
31
38
|
end
|
32
39
|
|
33
40
|
module Constants
|
@@ -97,6 +97,7 @@ module Cassandra
|
|
97
97
|
when :bigint, :counter then write_bigint(buffer, value)
|
98
98
|
when :blob then write_blob(buffer, value)
|
99
99
|
when :boolean then write_boolean(buffer, value)
|
100
|
+
when :custom then write_custom(buffer, value, type)
|
100
101
|
when :decimal then write_decimal(buffer, value)
|
101
102
|
when :double then write_double(buffer, value)
|
102
103
|
when :float then write_float(buffer, value)
|
@@ -221,19 +222,19 @@ module Cassandra
|
|
221
222
|
end
|
222
223
|
end
|
223
224
|
|
224
|
-
def read_values_v4(buffer, column_metadata)
|
225
|
+
def read_values_v4(buffer, column_metadata, custom_type_handlers)
|
225
226
|
::Array.new(buffer.read_int) do |_i|
|
226
227
|
row = ::Hash.new
|
227
228
|
|
228
229
|
column_metadata.each do |(_, _, column, type)|
|
229
|
-
row[column] = read_value_v4(buffer, type)
|
230
|
+
row[column] = read_value_v4(buffer, type, custom_type_handlers)
|
230
231
|
end
|
231
232
|
|
232
233
|
row
|
233
234
|
end
|
234
235
|
end
|
235
236
|
|
236
|
-
def read_value_v4(buffer, type)
|
237
|
+
def read_value_v4(buffer, type, custom_type_handlers)
|
237
238
|
case type.kind
|
238
239
|
when :ascii then read_ascii(buffer)
|
239
240
|
when :bigint, :counter then read_bigint(buffer)
|
@@ -253,11 +254,12 @@ module Cassandra
|
|
253
254
|
when :smallint then read_smallint(buffer)
|
254
255
|
when :time then read_time(buffer)
|
255
256
|
when :date then read_date(buffer)
|
257
|
+
when :custom then read_custom(buffer, type, custom_type_handlers)
|
256
258
|
when :list
|
257
259
|
return nil unless read_size(buffer)
|
258
260
|
|
259
261
|
value_type = type.value_type
|
260
|
-
::Array.new(buffer.read_signed_int) { read_value_v4(buffer, value_type) }
|
262
|
+
::Array.new(buffer.read_signed_int) { read_value_v4(buffer, value_type, custom_type_handlers) }
|
261
263
|
when :map
|
262
264
|
return nil unless read_size(buffer)
|
263
265
|
|
@@ -266,7 +268,7 @@ module Cassandra
|
|
266
268
|
value = ::Hash.new
|
267
269
|
|
268
270
|
buffer.read_signed_int.times do
|
269
|
-
value[read_value_v4(buffer, key_type)] = read_value_v4(buffer, value_type)
|
271
|
+
value[read_value_v4(buffer, key_type, custom_type_handlers)] = read_value_v4(buffer, value_type, custom_type_handlers)
|
270
272
|
end
|
271
273
|
|
272
274
|
value
|
@@ -277,7 +279,7 @@ module Cassandra
|
|
277
279
|
value = ::Set.new
|
278
280
|
|
279
281
|
buffer.read_signed_int.times do
|
280
|
-
value << read_value_v4(buffer, value_type)
|
282
|
+
value << read_value_v4(buffer, value_type, custom_type_handlers)
|
281
283
|
end
|
282
284
|
|
283
285
|
value
|
@@ -295,7 +297,7 @@ module Cassandra
|
|
295
297
|
values[field.name] = if length - buffer.length >= size
|
296
298
|
nil
|
297
299
|
else
|
298
|
-
read_value_v4(buffer, field.type)
|
300
|
+
read_value_v4(buffer, field.type, custom_type_handlers)
|
299
301
|
end
|
300
302
|
end
|
301
303
|
|
@@ -308,7 +310,7 @@ module Cassandra
|
|
308
310
|
|
309
311
|
members.each do |member_type|
|
310
312
|
break if buffer.empty?
|
311
|
-
values << read_value_v4(buffer, member_type)
|
313
|
+
values << read_value_v4(buffer, member_type, custom_type_handlers)
|
312
314
|
end
|
313
315
|
|
314
316
|
values.fill(nil, values.length, (members.length - values.length))
|
@@ -774,6 +776,15 @@ module Cassandra
|
|
774
776
|
read_size(buffer) && buffer.read(1) == Constants::TRUE_BYTE
|
775
777
|
end
|
776
778
|
|
779
|
+
def read_custom(buffer, type, custom_type_handlers)
|
780
|
+
# Lookup the type-name to get the Class that can deserialize buffer data into a custom domain object.
|
781
|
+
unless custom_type_handlers && custom_type_handlers.key?(type)
|
782
|
+
raise Errors::DecodingError, %(Unsupported custom column type: #{type.name})
|
783
|
+
end
|
784
|
+
num_bytes = read_size(buffer)
|
785
|
+
custom_type_handlers[type].deserialize(buffer.read(num_bytes)) if num_bytes && num_bytes > 0
|
786
|
+
end
|
787
|
+
|
777
788
|
def read_decimal(buffer)
|
778
789
|
size = read_size(buffer)
|
779
790
|
size && buffer.read_decimal(size)
|
@@ -860,6 +871,15 @@ module Cassandra
|
|
860
871
|
buffer.append(value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
|
861
872
|
end
|
862
873
|
|
874
|
+
def write_custom(buffer, value, type)
|
875
|
+
# Verify that the given type-name matches the value's cql type name.
|
876
|
+
if value.class.type != type
|
877
|
+
raise Errors::EncodingError, "type mismatch: value is a #{value.type} and column is a #{type}"
|
878
|
+
end
|
879
|
+
|
880
|
+
buffer.append_bytes(value.serialize)
|
881
|
+
end
|
882
|
+
|
863
883
|
def write_decimal(buffer, value)
|
864
884
|
buffer.append_bytes(CqlByteBuffer.new.append_decimal(value))
|
865
885
|
end
|
@@ -92,6 +92,13 @@ module Cassandra
|
|
92
92
|
"Not enough bytes available to decode a double: #{e.message}", e.backtrace
|
93
93
|
end
|
94
94
|
|
95
|
+
def read_double_le
|
96
|
+
read(8).unpack(Formats::DOUBLE_FORMAT_LE).first
|
97
|
+
rescue RangeError => e
|
98
|
+
raise Errors::DecodingError,
|
99
|
+
"Not enough bytes available to decode a double: #{e.message}", e.backtrace
|
100
|
+
end
|
101
|
+
|
95
102
|
def read_float
|
96
103
|
read(4).unpack(Formats::FLOAT_FORMAT).first
|
97
104
|
rescue RangeError => e
|
@@ -108,6 +115,13 @@ module Cassandra
|
|
108
115
|
"Not enough bytes available to decode an int: #{e.message}", e.backtrace
|
109
116
|
end
|
110
117
|
|
118
|
+
def read_unsigned_int_le
|
119
|
+
read(4).unpack(Formats::INT_FORMAT_LE).first
|
120
|
+
rescue RangeError => e
|
121
|
+
raise Errors::DecodingError,
|
122
|
+
"Not enough bytes available to decode an int: #{e.message}", e.backtrace
|
123
|
+
end
|
124
|
+
|
111
125
|
def read_unsigned_short
|
112
126
|
read_short
|
113
127
|
rescue RangeError => e
|
@@ -115,6 +129,13 @@ module Cassandra
|
|
115
129
|
"Not enough bytes available to decode a short: #{e.message}", e.backtrace
|
116
130
|
end
|
117
131
|
|
132
|
+
def read_unsigned_short_le
|
133
|
+
read(2).unpack(Formats::SHORT_FORMAT_LE).first
|
134
|
+
rescue RangeError => e
|
135
|
+
raise Errors::DecodingError,
|
136
|
+
"Not enough bytes available to decode a short: #{e.message}", e.backtrace
|
137
|
+
end
|
138
|
+
|
118
139
|
def read_string
|
119
140
|
length = read_unsigned_short
|
120
141
|
string = read(length)
|
@@ -46,7 +46,8 @@ module Cassandra
|
|
46
46
|
compressor = nil,
|
47
47
|
heartbeat_interval = 30,
|
48
48
|
idle_timeout = 60,
|
49
|
-
requests_per_connection = 128
|
49
|
+
requests_per_connection = 128,
|
50
|
+
custom_type_handlers = {})
|
50
51
|
@protocol_version = protocol_version
|
51
52
|
@connection = connection
|
52
53
|
@scheduler = scheduler
|
@@ -60,7 +61,7 @@ module Cassandra
|
|
60
61
|
|
61
62
|
if protocol_version > 3
|
62
63
|
@frame_encoder = V4::Encoder.new(@compressor, protocol_version)
|
63
|
-
@frame_decoder = V4::Decoder.new(self, @compressor)
|
64
|
+
@frame_decoder = V4::Decoder.new(self, @compressor, custom_type_handlers)
|
64
65
|
elsif protocol_version > 2
|
65
66
|
@frame_encoder = V3::Encoder.new(@compressor, protocol_version)
|
66
67
|
@frame_decoder = V3::Decoder.new(self, @compressor)
|
@@ -24,17 +24,19 @@ module Cassandra
|
|
24
24
|
protocol_version,
|
25
25
|
raw_rows,
|
26
26
|
paging_state,
|
27
|
-
trace_id
|
27
|
+
trace_id,
|
28
|
+
custom_type_handlers = nil)
|
28
29
|
super(custom_payload, warnings, nil, nil, paging_state, trace_id)
|
29
30
|
@protocol_version = protocol_version
|
30
31
|
@raw_rows = raw_rows
|
32
|
+
@custom_type_handlers = custom_type_handlers
|
31
33
|
end
|
32
34
|
|
33
35
|
def materialize(metadata)
|
34
36
|
@metadata = metadata
|
35
37
|
|
36
38
|
@rows = if @protocol_version == 4
|
37
|
-
Coder.read_values_v4(@raw_rows, @metadata)
|
39
|
+
Coder.read_values_v4(@raw_rows, @metadata, @custom_type_handlers)
|
38
40
|
elsif @protocol_version == 3
|
39
41
|
Coder.read_values_v3(@raw_rows, @metadata)
|
40
42
|
else
|
@@ -59,7 +59,7 @@ module Cassandra
|
|
59
59
|
end
|
60
60
|
|
61
61
|
class Decoder
|
62
|
-
def initialize(handler, compressor = nil)
|
62
|
+
def initialize(handler, compressor = nil, custom_type_handlers = {})
|
63
63
|
@handler = handler
|
64
64
|
@compressor = compressor
|
65
65
|
@state = :initial
|
@@ -68,6 +68,7 @@ module Cassandra
|
|
68
68
|
@code = nil
|
69
69
|
@length = nil
|
70
70
|
@buffer = CqlByteBuffer.new
|
71
|
+
@custom_type_handlers = custom_type_handlers
|
71
72
|
end
|
72
73
|
|
73
74
|
def <<(data)
|
@@ -325,11 +326,12 @@ module Cassandra
|
|
325
326
|
protocol_version,
|
326
327
|
remaining_bytes,
|
327
328
|
paging_state,
|
328
|
-
trace_id
|
329
|
+
trace_id,
|
330
|
+
@custom_type_handlers)
|
329
331
|
else
|
330
332
|
RowsResultResponse.new(custom_payload,
|
331
333
|
warnings,
|
332
|
-
Coder.read_values_v4(buffer, column_specs),
|
334
|
+
Coder.read_values_v4(buffer, column_specs, @custom_type_handlers),
|
333
335
|
column_specs,
|
334
336
|
paging_state,
|
335
337
|
trace_id)
|
data/lib/cassandra/result.rb
CHANGED
@@ -76,8 +76,8 @@ module Cassandra
|
|
76
76
|
#
|
77
77
|
# @note `:paging_state` option will be ignored.
|
78
78
|
#
|
79
|
-
# @return [Cassandra::Future<Cassandra::Result
|
80
|
-
#
|
79
|
+
# @return [Cassandra::Future<Cassandra::Result>] a future that resolves to a new Result if there is a new page,
|
80
|
+
# `nil` otherwise.
|
81
81
|
#
|
82
82
|
# @see Cassandra::Session#execute
|
83
83
|
def next_page_async(options = nil)
|
data/lib/cassandra/session.rb
CHANGED
@@ -89,20 +89,13 @@ module Cassandra
|
|
89
89
|
|
90
90
|
case statement
|
91
91
|
when ::String
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
when
|
98
|
-
@client
|
99
|
-
when Statements::Prepared
|
100
|
-
@client.execute(statement.bind(options.arguments), options)
|
101
|
-
when Statements::Bound
|
102
|
-
@client.execute(statement, options)
|
103
|
-
when Statements::Batch
|
104
|
-
Util.assert_not_empty(statement.statements) { 'batch cannot be empty' }
|
105
|
-
@client.batch(statement, options)
|
92
|
+
Statements::Simple.new(statement,
|
93
|
+
options.arguments,
|
94
|
+
options.type_hints,
|
95
|
+
options.idempotent?).accept(@client,
|
96
|
+
options)
|
97
|
+
when Statement
|
98
|
+
statement.accept(@client, options)
|
106
99
|
else
|
107
100
|
@futures.error(::ArgumentError.new("unsupported statement #{statement.inspect}"))
|
108
101
|
end
|
data/lib/cassandra/statement.rb
CHANGED
@@ -113,6 +113,12 @@ module Cassandra
|
|
113
113
|
self
|
114
114
|
end
|
115
115
|
|
116
|
+
# @private
|
117
|
+
def accept(client, options)
|
118
|
+
Util.assert_not_empty(statements) { 'batch cannot be empty' }
|
119
|
+
client.batch(self, options)
|
120
|
+
end
|
121
|
+
|
116
122
|
# Determines whether or not the statement is safe to retry on timeout
|
117
123
|
# Batches are idempotent only when all statements in a batch are.
|
118
124
|
# @return [Boolean] whether the statement is safe to retry on timeout
|
@@ -46,6 +46,11 @@ module Cassandra
|
|
46
46
|
@idempotent = idempotent
|
47
47
|
end
|
48
48
|
|
49
|
+
# @private
|
50
|
+
def accept(client, options)
|
51
|
+
client.execute(self, options)
|
52
|
+
end
|
53
|
+
|
49
54
|
# @return [String] a CLI-friendly bound statement representation
|
50
55
|
def inspect
|
51
56
|
"#<#{self.class.name}:0x#{object_id.to_s(16)} @cql=#{@cql.inspect} " \
|
@@ -155,6 +155,11 @@ module Cassandra
|
|
155
155
|
nil)
|
156
156
|
end
|
157
157
|
|
158
|
+
# @private
|
159
|
+
def accept(client, options)
|
160
|
+
client.execute(bind(options.arguments), options)
|
161
|
+
end
|
162
|
+
|
158
163
|
# @return [String] a CLI-friendly prepared statement representation
|
159
164
|
def inspect
|
160
165
|
"#<#{self.class.name}:0x#{object_id.to_s(16)} @cql=#{@cql.inspect}>"
|
@@ -180,7 +185,9 @@ module Cassandra
|
|
180
185
|
'the partition key and must be present.'
|
181
186
|
end
|
182
187
|
|
183
|
-
if @connection_options.protocol_version >=
|
188
|
+
if @connection_options.protocol_version >= 4
|
189
|
+
Protocol::Coder.write_value_v4(buffer, value, type)
|
190
|
+
elsif @connection_options.protocol_version >= 3
|
184
191
|
Protocol::Coder.write_value_v3(buffer, value, type)
|
185
192
|
else
|
186
193
|
Protocol::Coder.write_value_v1(buffer, value, type)
|
@@ -200,7 +207,9 @@ module Cassandra
|
|
200
207
|
'the partition key and must be present.'
|
201
208
|
end
|
202
209
|
|
203
|
-
if @connection_options.protocol_version >=
|
210
|
+
if @connection_options.protocol_version >= 4
|
211
|
+
Protocol::Coder.write_value_v4(buf, value, type)
|
212
|
+
elsif @connection_options.protocol_version >= 3
|
204
213
|
Protocol::Coder.write_value_v3(buf, value, type)
|
205
214
|
else
|
206
215
|
Protocol::Coder.write_value_v1(buf, value, type)
|
@@ -93,6 +93,11 @@ module Cassandra
|
|
93
93
|
@idempotent = idempotent
|
94
94
|
end
|
95
95
|
|
96
|
+
# @private
|
97
|
+
def accept(client, options)
|
98
|
+
client.query(self, options)
|
99
|
+
end
|
100
|
+
|
96
101
|
# @return [String] a CLI-friendly simple statement representation
|
97
102
|
def inspect
|
98
103
|
"#<#{self.class.name}:0x#{object_id.to_s(16)} @cql=#{@cql.inspect} " \
|
data/lib/cassandra/tuple.rb
CHANGED
@@ -55,7 +55,7 @@ module Cassandra
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def inspect
|
58
|
-
"#<Cassandra::Tuple:0x#{object_id.to_s(16)}
|
58
|
+
"#<Cassandra::Tuple:0x#{object_id.to_s(16)} types=#{@types.inspect}, []=#{@values.inspect}>"
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -114,7 +114,7 @@ module Cassandra
|
|
114
114
|
|
115
115
|
# @private
|
116
116
|
def inspect
|
117
|
-
"#<Cassandra::Tuple:0x#{object_id.to_s(16)}
|
117
|
+
"#<Cassandra::Tuple:0x#{object_id.to_s(16)} []=#{@values.inspect}>"
|
118
118
|
end
|
119
119
|
|
120
120
|
# @private
|
data/lib/cassandra/types.rb
CHANGED
@@ -1389,8 +1389,8 @@ module Cassandra
|
|
1389
1389
|
# @raise [ArgumentError] if the value is invalid
|
1390
1390
|
# @return [void]
|
1391
1391
|
def assert(value, message = nil, &block)
|
1392
|
-
|
1393
|
-
|
1392
|
+
Util.assert_instance_of(CustomData, value, message, &block)
|
1393
|
+
Util.assert_equal(self, value.class.type, message, &block)
|
1394
1394
|
end
|
1395
1395
|
|
1396
1396
|
# @return [String] a cassandra representation of this type
|
data/lib/cassandra/util.rb
CHANGED
@@ -196,6 +196,7 @@ module Cassandra
|
|
196
196
|
Types.udt(object.keyspace, object.name, object.types)
|
197
197
|
when UDT
|
198
198
|
Types.udt('unknown', 'unknown', object.map {|k, v| [k, guess_type(v)]})
|
199
|
+
when Cassandra::CustomData then object.class.type
|
199
200
|
else
|
200
201
|
raise ::ArgumentError,
|
201
202
|
"Unable to guess the type of the argument: #{object.inspect}"
|
data/lib/cassandra/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cassandra-driver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Theo Hultberg
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-06-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: ione
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/cassandra/compression.rb
|
108
108
|
- lib/cassandra/compression/compressors/lz4.rb
|
109
109
|
- lib/cassandra/compression/compressors/snappy.rb
|
110
|
+
- lib/cassandra/custom_data.rb
|
110
111
|
- lib/cassandra/driver.rb
|
111
112
|
- lib/cassandra/errors.rb
|
112
113
|
- lib/cassandra/execution/info.rb
|