cassandra-driver 3.0.0.rc.1 → 3.0.0.rc.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.
Files changed (64) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +6 -1
  3. data/lib/cassandra.rb +74 -55
  4. data/lib/cassandra/attr_boolean.rb +33 -0
  5. data/lib/cassandra/auth.rb +2 -1
  6. data/lib/cassandra/auth/providers/password.rb +4 -16
  7. data/lib/cassandra/cluster/connector.rb +14 -4
  8. data/lib/cassandra/cluster/control_connection.rb +59 -67
  9. data/lib/cassandra/cluster/metadata.rb +1 -3
  10. data/lib/cassandra/cluster/options.rb +9 -10
  11. data/lib/cassandra/cluster/registry.rb +16 -5
  12. data/lib/cassandra/cluster/schema.rb +45 -1
  13. data/lib/cassandra/cluster/schema/fetchers.rb +475 -272
  14. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +2 -6
  15. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +5 -7
  16. data/lib/cassandra/column.rb +1 -20
  17. data/lib/cassandra/column_container.rb +322 -0
  18. data/lib/cassandra/compression/compressors/lz4.rb +3 -5
  19. data/lib/cassandra/driver.rb +1 -1
  20. data/lib/cassandra/errors.rb +38 -22
  21. data/lib/cassandra/execution/options.rb +4 -2
  22. data/lib/cassandra/future.rb +3 -9
  23. data/lib/cassandra/host.rb +16 -2
  24. data/lib/cassandra/index.rb +104 -0
  25. data/lib/cassandra/keyspace.rb +88 -9
  26. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +6 -10
  27. data/lib/cassandra/materialized_view.rb +90 -0
  28. data/lib/cassandra/protocol/coder.rb +3 -3
  29. data/lib/cassandra/protocol/cql_byte_buffer.rb +12 -11
  30. data/lib/cassandra/protocol/cql_protocol_handler.rb +12 -8
  31. data/lib/cassandra/protocol/request.rb +4 -5
  32. data/lib/cassandra/protocol/requests/execute_request.rb +3 -5
  33. data/lib/cassandra/protocol/requests/query_request.rb +1 -1
  34. data/lib/cassandra/protocol/requests/startup_request.rb +6 -8
  35. data/lib/cassandra/protocol/response.rb +1 -2
  36. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +3 -4
  37. data/lib/cassandra/protocol/responses/auth_success_response.rb +3 -4
  38. data/lib/cassandra/protocol/responses/authenticate_response.rb +3 -4
  39. data/lib/cassandra/protocol/responses/error_response.rb +3 -4
  40. data/lib/cassandra/protocol/responses/event_response.rb +2 -3
  41. data/lib/cassandra/protocol/responses/prepared_result_response.rb +3 -4
  42. data/lib/cassandra/protocol/responses/ready_response.rb +3 -4
  43. data/lib/cassandra/protocol/responses/result_response.rb +7 -8
  44. data/lib/cassandra/protocol/responses/rows_result_response.rb +3 -4
  45. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +3 -4
  46. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +3 -4
  47. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +3 -4
  48. data/lib/cassandra/protocol/responses/status_change_event_response.rb +3 -4
  49. data/lib/cassandra/protocol/responses/supported_response.rb +3 -4
  50. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +3 -4
  51. data/lib/cassandra/protocol/responses/void_result_response.rb +3 -4
  52. data/lib/cassandra/protocol/v1.rb +1 -5
  53. data/lib/cassandra/protocol/v3.rb +1 -3
  54. data/lib/cassandra/result.rb +2 -1
  55. data/lib/cassandra/retry/policies/downgrading_consistency.rb +1 -3
  56. data/lib/cassandra/statements/prepared.rb +3 -3
  57. data/lib/cassandra/table.rb +39 -220
  58. data/lib/cassandra/time_uuid.rb +5 -7
  59. data/lib/cassandra/tuple.rb +4 -12
  60. data/lib/cassandra/types.rb +92 -65
  61. data/lib/cassandra/udt.rb +34 -14
  62. data/lib/cassandra/uuid.rb +10 -18
  63. data/lib/cassandra/version.rb +1 -1
  64. metadata +8 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTFhMzk5ZGFjZWJhYTQzZDFhYjA5ZGM3Mzk0YjY1MWMwODdjMDUyNA==
4
+ ZTBiZDQ4YTM2MDliN2U0N2VlNmJjY2RiYjQyOWVlOWI4MzlhNjNkZg==
5
5
  data.tar.gz: !binary |-
6
- NGE5OTQ1YjYyNjA1ZTVhNDI4OGQzNmJiMmFlMzJlNzRlMzNiMTkyMw==
6
+ OGY1MDNjN2Y5ZmFjYmY2YWY0ZWI0ZGNjZjViMTA1ZDdkYzQyOTg0Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MWZiZmZiOWNkMzFkMDM3NzE3ZTQxMzUzZWM5NjU1MjA1ODI2ODFkNDkxNzI4
10
- YjlmNmJhZGE2OTEyNWY1ZmIyOWQwNjhlNTQyNjdiN2U2Njk3ZDYyMzNhYTg4
11
- NmZjYjY5YmZiMDRlNTA2Njg4ZTQ2YTJlZWQ3YjVhY2MwNGE0NjA=
9
+ MTIzOTk1Nzk0NDI2NWNkZWNiZmUyMmIzZjk4YjQ2YmRjZDkwODc4YjUxY2Fj
10
+ N2FmYjRlOGZiMjBlNTAzY2RmOGM4OGNlZmZkZWVjN2RjNDU1ZjY4MjYxODE3
11
+ YWU1MTZiNWMyMjViOTVhODExODlkNmQwMzc1ODZlMjkwYWU0NDQ=
12
12
  data.tar.gz: !binary |-
13
- NDJiNzQ1ZTgzN2VkOTBmYWZjOGFmN2QwMDc4OWU3YmQxMjdlYmFjZGQ0OTM5
14
- NDlmYmQxMDE1YjczZmNmZjg4MGRjNDY1ODRhZjNlYzBkODE2YTQ5YmM0Njlm
15
- N2IyYjhkM2JhZmUwMjUyM2I4ODhlM2VmY2Q5YmNkZTUzZmM1ZGE=
13
+ ZDI1ZDVmMWQyNzJiMGRiYzc5NTgxYjE4ZGEwNjVmZWM0Nzc0Yzk4MGJjODcx
14
+ YjEzYjNlNTZhOTU1YWY2M2JlZGUxZDA1YWU3NjRlMGE4ZmM4ODUyMTgyNmVj
15
+ NjU3NWUzYzFiMDNmOGJlZDg1ODJiYzJkMDQ3OGZhNjU3MWZlMTY=
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.github.io/ruby-driver/) or via the release tags, [e.g. v1.0.0-beta.3](https://github.com/datastax/ruby-driver/tree/v1.0.0-beta.3).*
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.github.io/ruby-driver/) or via the release tags, [e.g. v3.0.0-rc.2](https://github.com/datastax/ruby-driver/tree/v3.0.0-rc.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
 
@@ -107,6 +107,8 @@ Some of the new features added to the driver have unfortunately led to changes i
107
107
  * Expose server warnings on server exceptions and Cassandra::Execution::Info instances.
108
108
  * Add connections_per_local_node, connections_per_remote_node, requests_per_connection cluster configuration options to tune parallel query execution and resource usage.
109
109
  * Add Cassandra::Logger class to make it easy for users to enable debug logging in the client.
110
+ * Add protocol_version configuration option to allow the user to force the protocol version to use for communication with nodes.
111
+ * Add support for materialized views and indexes in the schema metadata.
110
112
 
111
113
  ### Breaking Changes:
112
114
 
@@ -133,6 +135,7 @@ batch.add(query, arguments: {p1: 'val1'})
133
135
  * [[RUBY-143](https://datastax-oss.atlassian.net/browse/RUBY-143)] Retry querying system table for metadata of new hosts when prior attempts fail, ultimately enabling use of new hosts.
134
136
  * [[RUBY-150](https://datastax-oss.atlassian.net/browse/RUBY-150)] Fixed a protocol decoding error that occurred when multiple messages are available in a stream.
135
137
  * [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
138
+ * [[RUBY-161](https://datastax-oss.atlassian.net/browse/RUBY-161)] Protocol version negotiation in mixed version clusters should not fall back to v1 unless it is truly warranted.
136
139
 
137
140
  ## Feedback Requested
138
141
 
@@ -191,6 +194,8 @@ the release.
191
194
 
192
195
  ## Known bugs & limitations
193
196
 
197
+ * Specifying a `protocol_version` option of 1 or 2 in cluster options will fail with a
198
+ `NoHostsAvailable` error rather than a `ProtocolError` against Cassandra node versions 3.0-3.4.
194
199
  * JRuby 1.6 is not officially supported, although 1.6.8 should work.
195
200
  * Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
196
201
  * Because the driver uses `IO#write_nonblock`, Windows is not supported.
@@ -34,8 +34,10 @@ require 'date'
34
34
 
35
35
  module Cassandra
36
36
  # A list of all supported request consistencies
37
- # @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 2.0
38
- # @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 1.2
37
+ # @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency
38
+ # levels in Apache Cassandra 2.0
39
+ # @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency
40
+ # levels in Apache Cassandra 1.2
39
41
  # @see Cassandra::Session#execute_async
40
42
  CONSISTENCIES = [:any, :one, :two, :three, :quorum, :all, :local_quorum,
41
43
  :each_quorum, :serial, :local_serial, :local_one].freeze
@@ -47,9 +49,52 @@ module Cassandra
47
49
  # A list of all possible write types that a
48
50
  # {Cassandra::Errors::WriteTimeoutError} can have.
49
51
  #
50
- # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L872-L887 Description of possible types of writes in Apache Cassandra native protocol spec v1
52
+ # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L872-L887 Description of
53
+ # possible types of writes in Apache Cassandra native protocol spec v1
51
54
  WRITE_TYPES = [:simple, :batch, :unlogged_batch, :counter, :batch_log].freeze
52
55
 
56
+ CLUSTER_OPTIONS = [
57
+ :address_resolution,
58
+ :address_resolution_policy,
59
+ :auth_provider,
60
+ :client_cert,
61
+ :client_timestamps,
62
+ :compression,
63
+ :compressor,
64
+ :connect_timeout,
65
+ :connections_per_local_node,
66
+ :connections_per_remote_node,
67
+ :consistency,
68
+ :credentials,
69
+ :datacenter,
70
+ :futures_factory,
71
+ :heartbeat_interval,
72
+ :hosts,
73
+ :idle_timeout,
74
+ :listeners,
75
+ :load_balancing_policy,
76
+ :logger,
77
+ :nodelay,
78
+ :reconnection_policy,
79
+ :retry_policy,
80
+ :page_size,
81
+ :passphrase,
82
+ :password,
83
+ :port,
84
+ :private_key,
85
+ :protocol_version,
86
+ :requests_per_connection,
87
+ :schema_refresh_delay,
88
+ :schema_refresh_timeout,
89
+ :server_cert,
90
+ :shuffle_replicas,
91
+ :ssl,
92
+ :synchronize_schema,
93
+ :timeout,
94
+ :trace,
95
+ :username
96
+ ].freeze
97
+
53
98
  # Creates a {Cassandra::Cluster Cluster instance}.
54
99
  #
55
100
  # @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
@@ -141,6 +186,10 @@ module Cassandra
141
186
  # for nodes that use the v3 or later protocol, and `128` for nodes that use the
142
187
  # v2 or earlier protocol.
143
188
  #
189
+ # @option options [Integer] :protocol_version (nil) Version of protocol to speak to
190
+ # nodes. By default, this is auto-negotiated to the lowest common protocol version
191
+ # that all nodes in `:hosts` speak.
192
+ #
144
193
  # @option options [Boolean] :client_timestamps (false) whether the driver
145
194
  # should send timestamps for each executed statement. Enabling this setting
146
195
  # allows mitigating Cassandra cluster clock skew because the timestamp of
@@ -274,49 +323,13 @@ module Cassandra
274
323
  # @private
275
324
  SSL_CLASSES = [::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext].freeze
276
325
 
326
+ # rubocop:disable Metrics/AbcSize
327
+ # rubocop:disable Metrics/CyclomaticComplexity
328
+ # rubocop:disable Metrics/PerceivedComplexity
277
329
  # @private
278
330
  def self.validate_and_massage_options(options)
279
331
  options = options.select do |key, _|
280
- [
281
- :address_resolution,
282
- :address_resolution_policy,
283
- :auth_provider,
284
- :client_cert,
285
- :client_timestamps,
286
- :compression,
287
- :compressor,
288
- :connect_timeout,
289
- :connections_per_local_node,
290
- :connections_per_remote_node,
291
- :consistency,
292
- :credentials,
293
- :datacenter,
294
- :futures_factory,
295
- :heartbeat_interval,
296
- :hosts,
297
- :idle_timeout,
298
- :listeners,
299
- :load_balancing_policy,
300
- :logger,
301
- :nodelay,
302
- :reconnection_policy,
303
- :retry_policy,
304
- :page_size,
305
- :passphrase,
306
- :password,
307
- :port,
308
- :private_key,
309
- :requests_per_connection,
310
- :schema_refresh_delay,
311
- :schema_refresh_timeout,
312
- :server_cert,
313
- :shuffle_replicas,
314
- :ssl,
315
- :synchronize_schema,
316
- :timeout,
317
- :trace,
318
- :username
319
- ].include?(key)
332
+ CLUSTER_OPTIONS.include?(key)
320
333
  end
321
334
 
322
335
  has_username = options.key?(:username)
@@ -608,12 +621,8 @@ module Cassandra
608
621
  end
609
622
 
610
623
  options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
611
-
612
624
  options[:trace] = !!options[:trace] if options.key?(:trace)
613
-
614
- if options.key?(:shuffle_replicas)
615
- options[:shuffle_replicas] = !!options[:shuffle_replicas]
616
- end
625
+ options[:shuffle_replicas] = !!options[:shuffle_replicas] if options.key?(:shuffle_replicas)
617
626
 
618
627
  if options.key?(:page_size)
619
628
  page_size = options[:page_size]
@@ -627,6 +636,16 @@ module Cassandra
627
636
  end
628
637
  end
629
638
 
639
+ if options.key?(:protocol_version)
640
+ protocol_version = options[:protocol_version]
641
+ unless protocol_version.nil?
642
+ Util.assert_instance_of(::Integer, protocol_version)
643
+ Util.assert_one_of(1..4, protocol_version) do
644
+ ":protocol_version must be a positive integer, #{protocol_version.inspect} given"
645
+ end
646
+ end
647
+ end
648
+
630
649
  if options.key?(:futures_factory)
631
650
  futures_factory = options[:futures_factory]
632
651
  methods = [:error, :value, :promise, :all]
@@ -662,13 +681,8 @@ module Cassandra
662
681
  end
663
682
  end
664
683
 
665
- if options.key?(:synchronize_schema)
666
- options[:synchronize_schema] = !!options[:synchronize_schema]
667
- end
668
-
669
- if options.key?(:client_timestamps)
670
- options[:client_timestamps] = !!options[:client_timestamps]
671
- end
684
+ options[:synchronize_schema] = !!options[:synchronize_schema] if options.key?(:synchronize_schema)
685
+ options[:client_timestamps] = !!options[:client_timestamps] if options.key?(:client_timestamps)
672
686
 
673
687
  if options.key?(:connections_per_local_node)
674
688
  connections_per_node = options[:connections_per_local_node]
@@ -733,6 +747,8 @@ module Cassandra
733
747
  DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2**31)
734
748
  end
735
749
 
750
+ require 'cassandra/attr_boolean'
751
+ require 'cassandra/version'
736
752
  require 'cassandra/uuid'
737
753
  require 'cassandra/time_uuid'
738
754
  require 'cassandra/tuple'
@@ -763,8 +779,11 @@ require 'cassandra/argument'
763
779
  require 'cassandra/function'
764
780
  require 'cassandra/function_collection'
765
781
  require 'cassandra/column'
782
+ require 'cassandra/column_container'
766
783
  require 'cassandra/table'
784
+ require 'cassandra/materialized_view'
767
785
  require 'cassandra/keyspace'
786
+ require 'cassandra/index'
768
787
 
769
788
  require 'cassandra/execution/info'
770
789
  require 'cassandra/execution/options'
@@ -0,0 +1,33 @@
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
+ # This file monkey-patches Module to have an attr_boolean method to make it easy
20
+ # for classes to define boolean instance variables with "foo?" reader methods.
21
+ # Inspired by http://stackoverflow.com/questions/4013591/attr-reader-with-question-mark-in-a-name
22
+ module Cassandra
23
+ module AttrBoolean
24
+ def attr_boolean(*names)
25
+ names.each do |name|
26
+ define_method(:"#{name}?") do
27
+ res = instance_variable_get(:"@#{name}")
28
+ !res.nil? && res != false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -59,7 +59,8 @@ module Cassandra
59
59
  # subclasses of this class, but need to implement the same methods. This
60
60
  # class exists only for documentation purposes.
61
61
  #
62
- # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273 Cassandra native protocol v2 SASL authentication
62
+ # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273 Cassandra
63
+ # native protocol v2 SASL authentication
63
64
  # @see Cassandra::Auth::Provider#create_authenticator
64
65
  class Authenticator
65
66
  # @!method initial_response
@@ -53,24 +53,12 @@ module Cassandra
53
53
  @password = password
54
54
  end
55
55
 
56
- # Returns a Password Authenticator only if
57
- # `org.apache.cassandra.auth.PasswordAuthenticator` is given.
58
- # @param authentication_class [String] must equal to
59
- # `org.apache.cassandra.auth.PasswordAuthenticator`
60
- # @return [Cassandra::Auth::Authenticator] when `authentication_class ==
61
- # "org.apache.cassandra.auth.PasswordAuthenticator"`
62
- # @return [nil] for all other values of `authentication_class`
56
+ # Returns a Password Authenticator
57
+ # @param authentication_class [String] ignored
58
+ # @return [Cassandra::Auth::Authenticator]
63
59
  def create_authenticator(authentication_class)
64
- if authentication_class == PASSWORD_AUTHENTICATOR_FQCN
65
- Authenticator.new(@username, @password)
66
- end
60
+ Authenticator.new(@username, @password)
67
61
  end
68
-
69
- private
70
-
71
- # @private
72
- PASSWORD_AUTHENTICATOR_FQCN =
73
- 'org.apache.cassandra.auth.PasswordAuthenticator'.freeze
74
62
  end
75
63
  end
76
64
  end
@@ -136,6 +136,7 @@ module Cassandra
136
136
  @connection_options.idle_timeout,
137
137
  @connection_options.requests_per_connection)
138
138
  end.flat_map do |connection|
139
+ # connection is a CqlProtocolHandler
139
140
  f = request_options(connection)
140
141
  f = f.flat_map do |options|
141
142
  compression = @connection_options.compression
@@ -159,10 +160,19 @@ module Cassandra
159
160
  case error
160
161
  when Errors::ProtocolError
161
162
  synchronize do
162
- if @connection_options.protocol_version > 1
163
+ current_version = connection.protocol_version
164
+ if current_version > 1 && @connection_options.protocol_negotiable?
163
165
  @logger.info("Host #{host.ip} doesn't support protocol version " \
164
- "#{@connection_options.protocol_version}, downgrading")
165
- @connection_options.protocol_version -= 1
166
+ "#{current_version}, downgrading")
167
+
168
+ # This is tricky. We want to try with the next lower protocol version.
169
+ # However, the connection_options used for all connections may have
170
+ # already been updated due to other node connection failures. So,
171
+ # it may already have a lower protocol-version than our current-1. We
172
+ # don't want to accidentally raise it, so we update it to the min
173
+ # of itself and current-1.
174
+ @connection_options.protocol_version =
175
+ [@connection_options.protocol_version, current_version - 1].min
166
176
  do_connect(host)
167
177
  else
168
178
  Ione::Future.failed(error)
@@ -170,7 +180,7 @@ module Cassandra
170
180
  end
171
181
  when Errors::TimeoutError
172
182
  future = Ione::CompletableFuture.new
173
- connection.close(error).on_complete do |_f|
183
+ connection.close(error).on_complete do |_|
174
184
  future.fail(error)
175
185
  end
176
186
  future
@@ -147,20 +147,20 @@ module Cassandra
147
147
  private
148
148
 
149
149
  SELECT_LOCAL = Protocol::QueryRequest.new(
150
- 'SELECT rack, data_center, host_id, release_version, tokens, partitioner ' \
150
+ 'SELECT * ' \
151
151
  'FROM system.local',
152
152
  EMPTY_LIST,
153
153
  EMPTY_LIST,
154
154
  :one)
155
155
  SELECT_PEERS = Protocol::QueryRequest.new(
156
- 'SELECT peer, rack, data_center, host_id, rpc_address, release_version, tokens ' \
156
+ 'SELECT * ' \
157
157
  'FROM system.peers',
158
158
  EMPTY_LIST,
159
159
  EMPTY_LIST,
160
160
  :one)
161
161
 
162
162
  SELECT_PEER_QUERY =
163
- 'SELECT rack, data_center, host_id, rpc_address, release_version, tokens ' \
163
+ 'SELECT * ' \
164
164
  'FROM system.peers ' \
165
165
  "WHERE peer = '%s'".freeze
166
166
 
@@ -191,18 +191,14 @@ module Cassandra
191
191
  def register_async
192
192
  connection = @connection
193
193
 
194
- if connection.nil?
195
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
196
- end
194
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
197
195
 
198
196
  request = Protocol::RegisterRequest.new(
199
197
  Protocol::TopologyChangeEventResponse::TYPE,
200
198
  Protocol::StatusChangeEventResponse::TYPE
201
199
  )
202
200
 
203
- if @connection_options.synchronize_schema?
204
- request.events << Protocol::SchemaChangeEventResponse::TYPE
205
- end
201
+ request.events << Protocol::SchemaChangeEventResponse::TYPE if @connection_options.synchronize_schema?
206
202
 
207
203
  f = connection.send_request(request)
208
204
  f = f.map do |r|
@@ -257,9 +253,7 @@ module Cassandra
257
253
 
258
254
  @logger.info('Refreshing schema')
259
255
 
260
- if connection.nil?
261
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
262
- end
256
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
263
257
 
264
258
  @schema_fetcher.fetch(connection).map do |keyspaces|
265
259
  @schema.replace(keyspaces)
@@ -271,9 +265,7 @@ module Cassandra
271
265
  def refresh_keyspace_async(keyspace_name)
272
266
  connection = @connection
273
267
 
274
- if connection.nil?
275
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
276
- end
268
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
277
269
 
278
270
  @logger.info("Refreshing keyspace \"#{keyspace_name}\"")
279
271
 
@@ -284,16 +276,14 @@ module Cassandra
284
276
  @schema.delete_keyspace(keyspace_name)
285
277
  end
286
278
 
287
- @logger.info("Refreshed keyspace \"#{keyspace_name}\"")
279
+ @logger.info("Completed refreshing keyspace \"#{keyspace_name}\"")
288
280
  end
289
281
  end
290
282
 
291
283
  def refresh_table_async(keyspace_name, table_name)
292
284
  connection = @connection
293
285
 
294
- if connection.nil?
295
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
296
- end
286
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
297
287
 
298
288
  @logger.info("Refreshing table \"#{keyspace_name}.#{table_name}\"")
299
289
 
@@ -304,16 +294,32 @@ module Cassandra
304
294
  @schema.delete_table(keyspace_name, table_name)
305
295
  end
306
296
 
307
- @logger.info("Refreshed table \"#{keyspace_name}.#{table_name}\"")
297
+ @logger.info("Completed refreshing table \"#{keyspace_name}.#{table_name}\"")
308
298
  end
309
299
  end
310
300
 
311
- def refresh_type_async(keyspace_name, type_name)
301
+ def refresh_materialized_view_async(keyspace_name, view_name)
312
302
  connection = @connection
313
303
 
314
- if connection.nil?
315
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
304
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
305
+
306
+ @logger.info("Refreshing materialized view \"#{keyspace_name}.#{view_name}\"")
307
+
308
+ @schema_fetcher.fetch_materialized_view(connection, keyspace_name, view_name).map do |view|
309
+ if view
310
+ @schema.replace_materialized_view(view)
311
+ else
312
+ @schema.delete_materialized_view(keyspace_name, view_name)
313
+ end
314
+
315
+ @logger.info("Completed refreshing materialized view \"#{keyspace_name}.#{view_name}\"")
316
316
  end
317
+ end
318
+
319
+ def refresh_type_async(keyspace_name, type_name)
320
+ connection = @connection
321
+
322
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
317
323
 
318
324
  @logger.info("Refreshing user-defined type \"#{keyspace_name}.#{type_name}\"")
319
325
 
@@ -324,16 +330,14 @@ module Cassandra
324
330
  @schema.delete_type(keyspace_name, type_name)
325
331
  end
326
332
 
327
- @logger.info("Refreshed user-defined type \"#{keyspace_name}.#{type_name}\"")
333
+ @logger.info("Completed refreshing user-defined type \"#{keyspace_name}.#{type_name}\"")
328
334
  end
329
335
  end
330
336
 
331
337
  def refresh_function_async(keyspace_name, function_name, function_args)
332
338
  connection = @connection
333
339
 
334
- if connection.nil?
335
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
336
- end
340
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
337
341
 
338
342
  @logger.info('Refreshing user-defined function ' \
339
343
  "\"#{keyspace_name}.#{function_name}\"")
@@ -351,7 +355,7 @@ module Cassandra
351
355
  @schema.delete_function(keyspace_name, function_name, parsed_function_args)
352
356
  end
353
357
 
354
- @logger.info('Refreshed user-defined function ' \
358
+ @logger.info('Completed refreshing user-defined function ' \
355
359
  "\"#{keyspace_name}.#{function_name}(#{function_args.join(',')})\"")
356
360
  end
357
361
  end
@@ -359,9 +363,7 @@ module Cassandra
359
363
  def refresh_aggregate_async(keyspace_name, aggregate_name, aggregate_args)
360
364
  connection = @connection
361
365
 
362
- if connection.nil?
363
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
364
- end
366
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
365
367
 
366
368
  @logger.info('Refreshing user-defined aggregate ' \
367
369
  "\"#{keyspace_name}.#{aggregate_name}\"")
@@ -380,7 +382,7 @@ module Cassandra
380
382
  @schema.delete_aggregate(keyspace_name, aggregate_name, parsed_aggregate_args)
381
383
  end
382
384
 
383
- @logger.info('Refreshed user-defined aggregate ' \
385
+ @logger.info('Completed refreshing user-defined aggregate ' \
384
386
  "\"#{keyspace_name}.#{aggregate_name}(#{aggregate_args.join(',')})\"")
385
387
  end
386
388
  end
@@ -432,9 +434,7 @@ module Cassandra
432
434
  def refresh_peers_async
433
435
  connection = @connection
434
436
 
435
- if connection.nil?
436
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
437
- end
437
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
438
438
 
439
439
  @logger.info('Refreshing peers metadata')
440
440
 
@@ -456,7 +456,7 @@ module Cassandra
456
456
  @registry.host_lost(host.ip) unless ips.include?(host.ip)
457
457
  end
458
458
 
459
- @logger.info('Refreshed peers metadata')
459
+ @logger.info('Completed refreshing peers metadata')
460
460
 
461
461
  nil
462
462
  end
@@ -465,22 +465,18 @@ module Cassandra
465
465
  def refresh_metadata_async
466
466
  connection = @connection
467
467
 
468
- if connection.nil?
469
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
470
- end
468
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
471
469
 
472
470
  @logger.info("Refreshing connected host's metadata")
473
471
 
474
472
  send_select_request(connection, SELECT_LOCAL).map do |local|
475
- if local.empty?
476
- raise Errors::InternalError, "Unable to fetch connected host's metadata"
477
- else
478
- data = local.first
479
- @registry.host_found(IPAddr.new(connection.host), data)
480
- @metadata.update(data)
481
- end
473
+ raise Errors::InternalError, "Unable to fetch connected host's metadata" if local.empty?
474
+
475
+ data = local.first
476
+ @registry.host_found(IPAddr.new(connection.host), data)
477
+ @metadata.update(data)
482
478
 
483
- @logger.info("Refreshed connected host's metadata")
479
+ @logger.info("Completed refreshing connected host's metadata")
484
480
 
485
481
  nil
486
482
  end
@@ -559,9 +555,7 @@ module Cassandra
559
555
 
560
556
  def refresh_host_async(address)
561
557
  connection = @connection
562
- if connection.nil?
563
- return Ione::Future.failed(Errors::ClientError.new('Not connected'))
564
- end
558
+ return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
565
559
 
566
560
  ip = address.to_s
567
561
 
@@ -577,12 +571,10 @@ module Cassandra
577
571
  end
578
572
 
579
573
  send_select_request(connection, request).map do |rows|
580
- if rows.empty?
581
- raise Errors::InternalError, "Unable to find host metadata: #{ip}"
582
- else
583
- @logger.info("Refreshed host metadata: #{ip}")
584
- @registry.host_found(address, rows.first)
585
- end
574
+ raise Errors::InternalError, "Unable to find host metadata: #{ip}" if rows.empty?
575
+
576
+ @logger.info("Completed refreshing host metadata: #{ip}")
577
+ @registry.host_found(address, rows.first)
586
578
 
587
579
  self
588
580
  end
@@ -647,9 +639,7 @@ Control connection failed and is unlikely to recover.
647
639
  end
648
640
  f = f.flat_map { register_async }
649
641
  f = f.flat_map { refresh_peers_async_maybe_retry }
650
- if @connection_options.synchronize_schema?
651
- f = f.flat_map { refresh_maybe_retry(:schema) }
652
- end
642
+ f = f.flat_map { refresh_maybe_retry(:schema) } if @connection_options.synchronize_schema?
653
643
  f = f.fallback do |error|
654
644
  @logger.debug("Connection to #{host.ip} failed " \
655
645
  "(#{error.class.name}: #{error.message})")
@@ -683,8 +673,8 @@ Control connection failed and is unlikely to recover.
683
673
  end
684
674
 
685
675
  def process_schema_changes(schema_changes)
686
- refresh_keyspaces = ::Hash.new
687
- refresh_tables = ::Hash.new
676
+ refresh_keyspaces = ::Hash.new
677
+ refresh_tables_and_views = ::Hash.new
688
678
  refresh_types = ::Hash.new
689
679
 
690
680
  # This hash is of the form <keyspace, [Change (for function changes)]>
@@ -700,14 +690,15 @@ Control connection failed and is unlikely to recover.
700
690
 
701
691
  case change.target
702
692
  when Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
703
- refresh_tables.delete(keyspace)
693
+ refresh_tables_and_views.delete(keyspace)
704
694
  refresh_types.delete(keyspace)
705
695
  refresh_functions.delete(keyspace)
706
696
  refresh_aggregates.delete(keyspace)
707
697
  refresh_keyspaces[keyspace] = true
708
698
  when Protocol::Constants::SCHEMA_CHANGE_TARGET_TABLE
709
- tables = refresh_tables[keyspace] ||= ::Hash.new
710
- tables[change.name] = true
699
+ # We can't distinguish between table and view change events, so refresh both.
700
+ tables_and_views = refresh_tables_and_views[keyspace] ||= ::Hash.new
701
+ tables_and_views[change.name] = true
711
702
  when Protocol::Constants::SCHEMA_CHANGE_TARGET_UDT
712
703
  types = refresh_types[keyspace] ||= ::Hash.new
713
704
  types[change.name] = true
@@ -726,9 +717,10 @@ Control connection failed and is unlikely to recover.
726
717
  futures << refresh_maybe_retry(:keyspace, keyspace)
727
718
  end
728
719
 
729
- refresh_tables.each do |(keyspace, tables)|
730
- tables.each_key do |table|
731
- futures << refresh_maybe_retry(:table, keyspace, table)
720
+ refresh_tables_and_views.each do |(keyspace, tables_and_views)|
721
+ tables_and_views.each_key do |table_or_view|
722
+ futures << refresh_maybe_retry(:table, keyspace, table_or_view)
723
+ futures << refresh_maybe_retry(:materialized_view, keyspace, table_or_view)
732
724
  end
733
725
  end
734
726