cassandra-driver 3.0.0.rc.1-java → 3.0.0.rc.2-java

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 (65) hide show
  1. checksums.yaml +4 -4
  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. data/lib/cassandra_murmur3.jar +0 -0
  65. metadata +8 -2
@@ -52,8 +52,10 @@ module Cassandra
52
52
  # @return [nil, Hash<String, String>] custom outgoing payload, a map of
53
53
  # string and byte buffers.
54
54
  #
55
- # @see https://github.com/apache/cassandra/blob/33f1edcce97779c971d4f78712a9a8bf014ffbbc/doc/native_protocol_v4.spec#L127-L133 Description of custom payload in Cassandra native protocol v4.
56
- # @see https://datastax.github.io/java-driver/manual/custom_payloads/#enabling-custom-payloads-on-c-nodes Enabling custom payloads on Cassandra nodes.
55
+ # @see https://github.com/apache/cassandra/blob/cassandra-3.4/doc/native_protocol_v4.spec#L125-L131 Description
56
+ # of custom payload in Cassandra native protocol v4.
57
+ # @see https://datastax.github.io/java-driver/manual/custom_payloads/#enabling-custom-payloads-on-c-nodes
58
+ # Enabling custom payloads on Cassandra nodes.
57
59
  #
58
60
  # @example Sending a custom payload
59
61
  # result = session.execute(payload: {
@@ -46,9 +46,7 @@ module Cassandra
46
46
  # @private
47
47
  class Error < Future
48
48
  def initialize(error)
49
- unless error.is_a?(::Exception)
50
- raise ::ArgumentError, "error must be an exception, #{error.inspect} given"
51
- end
49
+ raise ::ArgumentError, "error must be an exception, #{error.inspect} given" unless error.is_a?(::Exception)
52
50
 
53
51
  @error = error
54
52
  end
@@ -519,9 +517,7 @@ module Cassandra
519
517
  end
520
518
 
521
519
  def failure(error)
522
- unless error.is_a?(::Exception)
523
- raise ::ArgumentError, "error must be an exception, #{error.inspect} given"
524
- end
520
+ raise ::ArgumentError, "error must be an exception, #{error.inspect} given" unless error.is_a?(::Exception)
525
521
 
526
522
  return unless @state == :pending
527
523
 
@@ -600,9 +596,7 @@ module Cassandra
600
596
  timeout &&= Float(timeout)
601
597
 
602
598
  if timeout
603
- if timeout < 0
604
- raise ::ArgumentError, "timeout cannot be negative, #{timeout.inspect} given"
605
- end
599
+ raise ::ArgumentError, "timeout cannot be negative, #{timeout.inspect} given" if timeout < 0
606
600
 
607
601
  start = ::Time.now
608
602
  now = start
@@ -18,7 +18,7 @@
18
18
 
19
19
  module Cassandra
20
20
  class Host
21
- # @return [IPAddr] host ip
21
+ # @return [IPAddr] host ip that clients use to connect to this host.
22
22
  attr_reader :ip
23
23
  # @note Host id can be `nil` before cluster has connected.
24
24
  # @return [Cassandra::Uuid, nil] host id.
@@ -37,6 +37,14 @@ module Cassandra
37
37
  attr_reader :tokens
38
38
  # @return [Symbol] host status. Must be `:up` or `:down`
39
39
  attr_reader :status
40
+ # @note This is the public IP address of the host if the cluster is deployed across multiple Amazon EC2 regions
41
+ # (or equivalently multiple networks). Cassandra nodes in other EC2 regions use this address to connect to this
42
+ # host.
43
+ # @return [IPAddr, String] broadcast address, if available.
44
+ attr_reader :broadcast_address
45
+ # @note This is the address that other Cassandra nodes use to connect to this host.
46
+ # @return [IPAddr, String] listen address, if available.
47
+ attr_reader :listen_address
40
48
 
41
49
  # @private
42
50
  def initialize(ip,
@@ -45,7 +53,9 @@ module Cassandra
45
53
  datacenter = nil,
46
54
  release_version = nil,
47
55
  tokens = EMPTY_LIST,
48
- status = :up)
56
+ status = :up,
57
+ broadcast_address = nil,
58
+ listen_address = nil)
49
59
  @ip = ip
50
60
  @id = id
51
61
  @rack = rack
@@ -53,6 +63,10 @@ module Cassandra
53
63
  @release_version = release_version
54
64
  @tokens = tokens
55
65
  @status = status
66
+ @broadcast_address = broadcast_address.is_a?(String) ?
67
+ ::IPAddr.new(broadcast_address) : broadcast_address
68
+ @listen_address = listen_address.is_a?(String) ?
69
+ ::IPAddr.new(listen_address) : listen_address
56
70
  end
57
71
 
58
72
  # @return [Boolean] whether this host's status is `:up`
@@ -0,0 +1,104 @@
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
+ module Cassandra
20
+ # Represents an index on a cassandra table
21
+ class Index
22
+ # @return [Cassandra::Table] table that the index applies to.
23
+ attr_reader :table
24
+ # @return [String] name of the index.
25
+ attr_reader :name
26
+ # @return [Symbol] kind of index: `:keys`, `:composites`, or `:custom`.
27
+ attr_reader :kind
28
+ # @return [String] name of column that the index applies to.
29
+ attr_reader :target
30
+ # @return [Hash] options of the index.
31
+ attr_reader :options
32
+
33
+ # @private
34
+ def initialize(table,
35
+ name,
36
+ kind,
37
+ target,
38
+ options)
39
+ @table = table
40
+ @name = name.freeze
41
+ @kind = kind
42
+ @target = target.freeze
43
+ @options = options.freeze
44
+ end
45
+
46
+ # @return [Boolean] whether or not this index uses a custom class.
47
+ def custom_index?
48
+ !@options['class_name'].nil?
49
+ end
50
+
51
+ # @return [String] name of the index class if this is a custom index; nil otherwise.
52
+ def custom_class_name
53
+ @options['class_name']
54
+ end
55
+
56
+ # @return [String] a cql representation of this table
57
+ def to_cql
58
+ keyspace_name = Util.escape_name(@table.keyspace.name)
59
+ table_name = Util.escape_name(@table.name)
60
+ index_name = Util.escape_name(name)
61
+
62
+ if custom_index?
63
+ "CREATE CUSTOM INDEX #{index_name} ON #{keyspace_name}.#{table_name} (#{target}) " \
64
+ "USING '#{@options['class_name']}' #{options_cql};"
65
+ else
66
+ "CREATE INDEX #{index_name} ON #{keyspace_name}.#{table_name} (#{target});"
67
+ end
68
+ end
69
+
70
+ # @private
71
+ def eql?(other)
72
+ other.is_a?(Index) &&
73
+ @table == other.table &&
74
+ @name == other.name &&
75
+ @kind == other.kind &&
76
+ @target == other.target &&
77
+ @options == other.options
78
+ end
79
+ alias == eql?
80
+
81
+ # @private
82
+ def inspect
83
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
84
+ "@name=#{@name} table_name=#{@table.name} kind=#{@kind} target=#{@target}>"
85
+ end
86
+
87
+ private
88
+
89
+ def options_cql
90
+ # exclude 'class_name', 'target' keys
91
+ filtered_options = @options.reject do |key, _|
92
+ key == 'class_name' || key == 'target'
93
+ end
94
+ return '' if filtered_options.empty?
95
+
96
+ result = 'WITH OPTIONS = {'
97
+ result << filtered_options.map do |key, value|
98
+ "'#{key}':'#{value}'"
99
+ end.join(', ')
100
+ result << '}'
101
+ result
102
+ end
103
+ end
104
+ end
@@ -57,7 +57,8 @@ module Cassandra
57
57
  tables,
58
58
  types,
59
59
  functions,
60
- aggregates)
60
+ aggregates,
61
+ views)
61
62
  @name = name
62
63
  @durable_writes = durable_writes
63
64
  @replication = replication
@@ -65,6 +66,15 @@ module Cassandra
65
66
  @types = types
66
67
  @functions = functions
67
68
  @aggregates = aggregates
69
+ @views = views
70
+
71
+ # Set the keyspace attribute on the tables and views.
72
+ @tables.each_value do |t|
73
+ t.set_keyspace(self)
74
+ end
75
+ @views.each_value do |v|
76
+ v.set_keyspace(self)
77
+ end
68
78
  end
69
79
 
70
80
  # @return [Boolean] whether durables writes are enabled for this keyspace
@@ -100,6 +110,34 @@ module Cassandra
100
110
  end
101
111
  alias tables each_table
102
112
 
113
+ # @return [Boolean] whether this keyspace has a materialized view with the given name
114
+ # @param name [String] materialized view name
115
+ def has_materialized_view?(name)
116
+ @views.key?(name)
117
+ end
118
+
119
+ # @return [Cassandra::MaterializedView, nil] a materialized view or nil
120
+ # @param name [String] materialized view name
121
+ def materialized_view(name)
122
+ @views[name]
123
+ end
124
+
125
+ # Yield or enumerate each materialized view defined in this keyspace
126
+ # @overload each_materialized_view
127
+ # @yieldparam view [Cassandra::MaterializedView] current materialized view
128
+ # @return [Cassandra::Keyspace] self
129
+ # @overload each_materialized_view
130
+ # @return [Array<Cassandra::MaterializedView>] a list of materialized views
131
+ def each_materialized_view(&block)
132
+ if block_given?
133
+ @views.each_value(&block)
134
+ self
135
+ else
136
+ @views.values
137
+ end
138
+ end
139
+ alias materialized_views each_materialized_view
140
+
103
141
  # @return [Boolean] whether this keyspace has a user-defined type with the
104
142
  # given name
105
143
  # @param name [String] user-defined type name
@@ -228,7 +266,8 @@ module Cassandra
228
266
  tables,
229
267
  @types,
230
268
  @functions,
231
- @aggregates)
269
+ @aggregates,
270
+ @views)
232
271
  end
233
272
 
234
273
  # @private
@@ -241,7 +280,36 @@ module Cassandra
241
280
  tables,
242
281
  @types,
243
282
  @functions,
244
- @aggregates)
283
+ @aggregates,
284
+ @views)
285
+ end
286
+
287
+ # @private
288
+ def update_materialized_view(view)
289
+ views = @views.dup
290
+ views[view.name] = view
291
+ Keyspace.new(@name,
292
+ @durable_writes,
293
+ @replication,
294
+ @tables,
295
+ @types,
296
+ @functions,
297
+ @aggregates,
298
+ views)
299
+ end
300
+
301
+ # @private
302
+ def delete_materialized_view(view_name)
303
+ views = @views.dup
304
+ views.delete(view_name)
305
+ Keyspace.new(@name,
306
+ @durable_writes,
307
+ @replication,
308
+ @tables,
309
+ @types,
310
+ @functions,
311
+ @aggregates,
312
+ views)
245
313
  end
246
314
 
247
315
  # @private
@@ -254,7 +322,8 @@ module Cassandra
254
322
  @tables,
255
323
  types,
256
324
  @functions,
257
- @aggregates)
325
+ @aggregates,
326
+ @views)
258
327
  end
259
328
 
260
329
  # @private
@@ -267,7 +336,8 @@ module Cassandra
267
336
  @tables,
268
337
  types,
269
338
  @functions,
270
- @aggregates)
339
+ @aggregates,
340
+ @views)
271
341
  end
272
342
 
273
343
  # @private
@@ -280,7 +350,8 @@ module Cassandra
280
350
  @tables,
281
351
  @types,
282
352
  functions,
283
- @aggregates)
353
+ @aggregates,
354
+ @views)
284
355
  end
285
356
 
286
357
  # @private
@@ -293,7 +364,8 @@ module Cassandra
293
364
  @tables,
294
365
  @types,
295
366
  functions,
296
- @aggregates)
367
+ @aggregates,
368
+ @views)
297
369
  end
298
370
 
299
371
  # @private
@@ -306,7 +378,8 @@ module Cassandra
306
378
  @tables,
307
379
  @types,
308
380
  @functions,
309
- aggregates)
381
+ aggregates,
382
+ @views)
310
383
  end
311
384
 
312
385
  # @private
@@ -319,7 +392,8 @@ module Cassandra
319
392
  @tables,
320
393
  @types,
321
394
  @functions,
322
- aggregates)
395
+ aggregates,
396
+ @views)
323
397
  end
324
398
 
325
399
  # @private
@@ -333,6 +407,11 @@ module Cassandra
333
407
  @tables
334
408
  end
335
409
 
410
+ # @private
411
+ def raw_materialized_views
412
+ @views
413
+ end
414
+
336
415
  # @private
337
416
  def raw_types
338
417
  @types
@@ -20,6 +20,11 @@ module Cassandra
20
20
  module LoadBalancing
21
21
  module Policies
22
22
  class DCAwareRoundRobin < Policy
23
+ # @private
24
+ LOCAL_CONSISTENCIES = [:local_quorum, :local_one].freeze
25
+ # @private
26
+ EMPTY_ARRAY = [].freeze
27
+
23
28
  # @private
24
29
  class Plan
25
30
  def initialize(local, remote, index)
@@ -62,9 +67,7 @@ module Cassandra
62
67
  datacenter &&= String(datacenter)
63
68
  max_remote_hosts_to_use &&= Integer(max_remote_hosts_to_use)
64
69
 
65
- unless datacenter.nil?
66
- Util.assert_not_empty(datacenter) { 'datacenter cannot be empty' }
67
- end
70
+ Util.assert_not_empty(datacenter) { 'datacenter cannot be empty' } unless datacenter.nil?
68
71
 
69
72
  unless max_remote_hosts_to_use.nil?
70
73
  Util.assert(max_remote_hosts_to_use >= 0) do
@@ -145,13 +148,6 @@ module Cassandra
145
148
 
146
149
  Plan.new(local, remote, position)
147
150
  end
148
-
149
- private
150
-
151
- # @private
152
- LOCAL_CONSISTENCIES = [:local_quorum, :local_one].freeze
153
- # @private
154
- EMPTY_ARRAY = [].freeze
155
151
  end
156
152
  end
157
153
  end
@@ -0,0 +1,90 @@
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
+ module Cassandra
20
+ # Represents a cassandra materialized view
21
+ # @see Cassandra::Keyspace#each_materialized_view
22
+ # @see Cassandra::Keyspace#materialized_view
23
+ class MaterializedView < ColumnContainer
24
+ # @return [Table] the table that this materialized view applies to.
25
+ attr_reader :base_table
26
+
27
+ # @private
28
+ def initialize(keyspace,
29
+ name,
30
+ partition_key,
31
+ clustering_columns,
32
+ other_columns,
33
+ options,
34
+ include_all_columns,
35
+ where_clause,
36
+ base_table,
37
+ id)
38
+ super(keyspace, name, partition_key, clustering_columns, other_columns, options, id)
39
+ @include_all_columns = include_all_columns
40
+ @where_clause = where_clause
41
+ @base_table = base_table
42
+ end
43
+
44
+ # @return [String] a cql representation of this materialized view
45
+ def to_cql
46
+ keyspace_name = Util.escape_name(@keyspace.name)
47
+ cql = "CREATE MATERIALIZED VIEW #{keyspace_name}.#{Util.escape_name(@name)} AS\nSELECT "
48
+ cql << if @include_all_columns
49
+ '*'
50
+ else
51
+ @columns.map do |column|
52
+ Util.escape_name(column.name)
53
+ end.join(', ')
54
+ end
55
+ cql << "\nFROM #{keyspace_name}.#{Util.escape_name(@base_table.name)}"
56
+ cql << "\nWHERE #{@where_clause}" if @where_clause
57
+ cql << "\nPRIMARY KEY (("
58
+ cql << @partition_key.map do |column|
59
+ Util.escape_name(column.name)
60
+ end.join(', ')
61
+ cql << ')'
62
+ unless @clustering_columns.empty?
63
+ cql << ', '
64
+ cql << @clustering_columns.map do |column|
65
+ Util.escape_name(column.name)
66
+ end.join(', ')
67
+ end
68
+ cql << ")\nWITH #{@options.to_cql.split("\n").join("\n ")};"
69
+ end
70
+
71
+ # @private
72
+ def eql?(other)
73
+ other.is_a?(MaterializedView) &&
74
+ super.eql?(other) &&
75
+ @include_all_columns == other.include_all_columns &&
76
+ @where_clause == other.where_clause &&
77
+ @base_table == other.base_table
78
+ end
79
+ alias == eql?
80
+
81
+ private
82
+
83
+ # We need these accessors for eql? to work, but we don't want random users to
84
+ # get these.
85
+
86
+ # @private
87
+ attr_reader :include_all_columns, :where_clause
88
+ protected :include_all_columns, :where_clause
89
+ end
90
+ end