cassandra-driver 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
[](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
|