cassandra-driver 3.0.0.beta.1-java → 3.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +106 -39
  3. data/lib/cassandra.rb +396 -148
  4. data/lib/cassandra/address_resolution.rb +1 -1
  5. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  7. data/lib/cassandra/aggregate.rb +21 -7
  8. data/lib/cassandra/argument.rb +2 -2
  9. data/lib/cassandra/attr_boolean.rb +33 -0
  10. data/lib/cassandra/auth.rb +6 -5
  11. data/lib/cassandra/auth/providers.rb +1 -1
  12. data/lib/cassandra/auth/providers/password.rb +5 -13
  13. data/lib/cassandra/cassandra_logger.rb +80 -0
  14. data/lib/cassandra/cluster.rb +49 -9
  15. data/lib/cassandra/cluster/client.rb +835 -209
  16. data/lib/cassandra/cluster/connection_pool.rb +2 -2
  17. data/lib/cassandra/cluster/connector.rb +86 -27
  18. data/lib/cassandra/cluster/control_connection.rb +222 -95
  19. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  20. data/lib/cassandra/cluster/metadata.rb +14 -8
  21. data/lib/cassandra/cluster/options.rb +68 -22
  22. data/lib/cassandra/cluster/registry.rb +81 -17
  23. data/lib/cassandra/cluster/schema.rb +70 -8
  24. data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
  25. data/lib/cassandra/cluster/schema/fetchers.rb +601 -241
  26. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +39 -38
  27. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  28. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +6 -8
  29. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
  30. data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
  31. data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
  32. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
  33. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
  34. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
  35. data/lib/cassandra/column.rb +4 -23
  36. data/lib/cassandra/column_container.rb +322 -0
  37. data/lib/cassandra/compression.rb +1 -1
  38. data/lib/cassandra/compression/compressors/lz4.rb +7 -8
  39. data/lib/cassandra/compression/compressors/snappy.rb +4 -3
  40. data/lib/cassandra/driver.rb +107 -46
  41. data/lib/cassandra/errors.rb +303 -52
  42. data/lib/cassandra/execution/info.rb +16 -5
  43. data/lib/cassandra/execution/options.rb +102 -55
  44. data/lib/cassandra/execution/trace.rb +16 -9
  45. data/lib/cassandra/executors.rb +1 -1
  46. data/lib/cassandra/function.rb +19 -13
  47. data/lib/cassandra/function_collection.rb +85 -0
  48. data/lib/cassandra/future.rb +101 -49
  49. data/lib/cassandra/host.rb +25 -5
  50. data/lib/cassandra/index.rb +118 -0
  51. data/lib/cassandra/keyspace.rb +169 -33
  52. data/lib/cassandra/listener.rb +1 -1
  53. data/lib/cassandra/load_balancing.rb +2 -2
  54. data/lib/cassandra/load_balancing/policies.rb +1 -1
  55. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +39 -25
  56. data/lib/cassandra/load_balancing/policies/round_robin.rb +8 -1
  57. data/lib/cassandra/load_balancing/policies/token_aware.rb +22 -13
  58. data/lib/cassandra/load_balancing/policies/white_list.rb +18 -5
  59. data/lib/cassandra/materialized_view.rb +90 -0
  60. data/lib/cassandra/null_logger.rb +27 -6
  61. data/lib/cassandra/protocol.rb +1 -1
  62. data/lib/cassandra/protocol/coder.rb +81 -42
  63. data/lib/cassandra/protocol/cql_byte_buffer.rb +58 -44
  64. data/lib/cassandra/protocol/cql_protocol_handler.rb +57 -54
  65. data/lib/cassandra/protocol/request.rb +6 -7
  66. data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
  67. data/lib/cassandra/protocol/requests/batch_request.rb +17 -8
  68. data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
  69. data/lib/cassandra/protocol/requests/execute_request.rb +39 -20
  70. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  71. data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
  72. data/lib/cassandra/protocol/requests/query_request.rb +28 -23
  73. data/lib/cassandra/protocol/requests/register_request.rb +2 -2
  74. data/lib/cassandra/protocol/requests/startup_request.rb +8 -8
  75. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  76. data/lib/cassandra/protocol/response.rb +3 -4
  77. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
  78. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +4 -5
  79. data/lib/cassandra/protocol/responses/auth_success_response.rb +4 -5
  80. data/lib/cassandra/protocol/responses/authenticate_response.rb +4 -5
  81. data/lib/cassandra/protocol/responses/error_response.rb +104 -17
  82. data/lib/cassandra/protocol/responses/event_response.rb +3 -4
  83. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
  84. data/lib/cassandra/protocol/responses/prepared_result_response.rb +14 -9
  85. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
  86. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
  87. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
  88. data/lib/cassandra/protocol/responses/ready_response.rb +6 -7
  89. data/lib/cassandra/protocol/responses/result_response.rb +11 -10
  90. data/lib/cassandra/protocol/responses/rows_result_response.rb +8 -7
  91. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +8 -8
  92. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +19 -13
  93. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +5 -6
  94. data/lib/cassandra/protocol/responses/status_change_event_response.rb +5 -6
  95. data/lib/cassandra/protocol/responses/supported_response.rb +4 -5
  96. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +4 -5
  97. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
  98. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
  99. data/lib/cassandra/protocol/responses/void_result_response.rb +4 -5
  100. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
  101. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
  102. data/lib/cassandra/protocol/v1.rb +98 -37
  103. data/lib/cassandra/protocol/v3.rb +121 -50
  104. data/lib/cassandra/protocol/v4.rb +172 -68
  105. data/lib/cassandra/reconnection.rb +1 -1
  106. data/lib/cassandra/reconnection/policies.rb +1 -1
  107. data/lib/cassandra/reconnection/policies/constant.rb +2 -4
  108. data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
  109. data/lib/cassandra/result.rb +55 -20
  110. data/lib/cassandra/retry.rb +8 -8
  111. data/lib/cassandra/retry/policies.rb +1 -1
  112. data/lib/cassandra/retry/policies/default.rb +1 -1
  113. data/lib/cassandra/retry/policies/downgrading_consistency.rb +4 -2
  114. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  115. data/lib/cassandra/session.rb +24 -16
  116. data/lib/cassandra/statement.rb +1 -1
  117. data/lib/cassandra/statements.rb +1 -1
  118. data/lib/cassandra/statements/batch.rb +16 -10
  119. data/lib/cassandra/statements/bound.rb +10 -3
  120. data/lib/cassandra/statements/prepared.rb +62 -18
  121. data/lib/cassandra/statements/simple.rb +23 -10
  122. data/lib/cassandra/statements/void.rb +1 -1
  123. data/lib/cassandra/table.rb +53 -185
  124. data/lib/cassandra/time.rb +11 -6
  125. data/lib/cassandra/time_uuid.rb +12 -14
  126. data/lib/cassandra/timestamp_generator.rb +37 -0
  127. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  128. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  129. data/lib/cassandra/tuple.rb +4 -4
  130. data/lib/cassandra/types.rb +109 -71
  131. data/lib/cassandra/udt.rb +66 -50
  132. data/lib/cassandra/util.rb +155 -15
  133. data/lib/cassandra/uuid.rb +20 -21
  134. data/lib/cassandra/uuid/generator.rb +7 -5
  135. data/lib/cassandra/version.rb +2 -2
  136. data/lib/cassandra_murmur3.jar +0 -0
  137. data/lib/datastax/cassandra.rb +1 -1
  138. metadata +27 -16
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -55,41 +55,53 @@ module Cassandra
55
55
  raise(@error, @error.message, @error.backtrace)
56
56
  end
57
57
 
58
- alias :join :get
58
+ alias join get
59
59
 
60
60
  def on_success
61
- raise ::ArgumentError, "no block given" unless block_given?
61
+ raise ::ArgumentError, 'no block given' unless block_given?
62
62
  self
63
63
  end
64
64
 
65
65
  def on_failure
66
- raise ::ArgumentError, "no block given" unless block_given?
67
- yield(@error) rescue nil
66
+ raise ::ArgumentError, 'no block given' unless block_given?
67
+ begin
68
+ yield(@error)
69
+ rescue
70
+ nil
71
+ end
68
72
  self
69
73
  end
70
74
 
71
75
  def on_complete
72
- raise ::ArgumentError, "no block given" unless block_given?
73
- yield(nil, @error) rescue nil
76
+ raise ::ArgumentError, 'no block given' unless block_given?
77
+ begin
78
+ yield(nil, @error)
79
+ rescue
80
+ nil
81
+ end
74
82
  self
75
83
  end
76
84
 
77
85
  def add_listener(listener)
78
- unless (listener.respond_to?(:success) && listener.respond_to?(:failure))
79
- raise ::ArgumentError, "listener must respond to both #success and #failure"
86
+ unless listener.respond_to?(:success) && listener.respond_to?(:failure)
87
+ raise ::ArgumentError, 'listener must respond to both #success and #failure'
80
88
  end
81
89
 
82
- listener.failure(@error) rescue nil
90
+ begin
91
+ listener.failure(@error)
92
+ rescue
93
+ nil
94
+ end
83
95
  self
84
96
  end
85
97
 
86
98
  def then
87
- raise ::ArgumentError, "no block given" unless block_given?
99
+ raise ::ArgumentError, 'no block given' unless block_given?
88
100
  self
89
101
  end
90
102
 
91
103
  def fallback
92
- raise ::ArgumentError, "no block given" unless block_given?
104
+ raise ::ArgumentError, 'no block given' unless block_given?
93
105
 
94
106
  begin
95
107
  result = yield(@error)
@@ -111,31 +123,43 @@ module Cassandra
111
123
  @value
112
124
  end
113
125
 
114
- alias :join :get
126
+ alias join get
115
127
 
116
128
  def on_success
117
- raise ::ArgumentError, "no block given" unless block_given?
118
- yield(@value) rescue nil
129
+ raise ::ArgumentError, 'no block given' unless block_given?
130
+ begin
131
+ yield(@value)
132
+ rescue
133
+ nil
134
+ end
119
135
  self
120
136
  end
121
137
 
122
138
  def on_failure
123
- raise ::ArgumentError, "no block given" unless block_given?
139
+ raise ::ArgumentError, 'no block given' unless block_given?
124
140
  self
125
141
  end
126
142
 
127
143
  def on_complete
128
- raise ::ArgumentError, "no block given" unless block_given?
129
- yield(@value, nil) rescue nil
144
+ raise ::ArgumentError, 'no block given' unless block_given?
145
+ begin
146
+ yield(@value, nil)
147
+ rescue
148
+ nil
149
+ end
130
150
  self
131
151
  end
132
152
 
133
153
  def add_listener(listener)
134
- unless (listener.respond_to?(:success) && listener.respond_to?(:failure))
135
- raise ::ArgumentError, "listener must respond to both #success and #failure"
154
+ unless listener.respond_to?(:success) && listener.respond_to?(:failure)
155
+ raise ::ArgumentError, 'listener must respond to both #success and #failure'
136
156
  end
137
157
 
138
- listener.success(@value) rescue nil
158
+ begin
159
+ listener.success(@value)
160
+ rescue
161
+ nil
162
+ end
139
163
  self
140
164
  end
141
165
 
@@ -144,7 +168,7 @@ module Cassandra
144
168
  end
145
169
 
146
170
  def then
147
- raise ::ArgumentError, "no block given" unless block_given?
171
+ raise ::ArgumentError, 'no block given' unless block_given?
148
172
 
149
173
  begin
150
174
  result = yield(@value)
@@ -156,7 +180,7 @@ module Cassandra
156
180
  end
157
181
 
158
182
  def fallback
159
- raise ::ArgumentError, "no block given" unless block_given?
183
+ raise ::ArgumentError, 'no block given' unless block_given?
160
184
  self
161
185
  end
162
186
  end
@@ -252,7 +276,7 @@ module Cassandra
252
276
  # @raise [ArgumentError] if no block given
253
277
  # @return [self]
254
278
  def on_success(&block)
255
- raise ::ArgumentError, "no block given" unless block_given?
279
+ raise ::ArgumentError, 'no block given' unless block_given?
256
280
  @signal.on_success(&block)
257
281
  self
258
282
  end
@@ -265,7 +289,7 @@ module Cassandra
265
289
  # @raise [ArgumentError] if no block given
266
290
  # @return [self]
267
291
  def on_failure(&block)
268
- raise ::ArgumentError, "no block given" unless block_given?
292
+ raise ::ArgumentError, 'no block given' unless block_given?
269
293
  @signal.on_failure(&block)
270
294
  self
271
295
  end
@@ -281,7 +305,7 @@ module Cassandra
281
305
  # @raise [ArgumentError] if no block given
282
306
  # @return [self]
283
307
  def on_complete(&block)
284
- raise ::ArgumentError, "no block given" unless block_given?
308
+ raise ::ArgumentError, 'no block given' unless block_given?
285
309
  @signal.on_complete(&block)
286
310
  self
287
311
  end
@@ -296,8 +320,8 @@ module Cassandra
296
320
  # `#success` and `#failure`
297
321
  # @return [self]
298
322
  def add_listener(listener)
299
- unless (listener.respond_to?(:success) && listener.respond_to?(:failure))
300
- raise ::ArgumentError, "listener must respond to both #success and #failure"
323
+ unless listener.respond_to?(:success) && listener.respond_to?(:failure)
324
+ raise ::ArgumentError, 'listener must respond to both #success and #failure'
301
325
  end
302
326
 
303
327
  @signal.add_listener(listener)
@@ -325,7 +349,7 @@ module Cassandra
325
349
  # @raise [ArgumentError] if no block given
326
350
  # @return [Cassandra::Future] a new future
327
351
  def then(&block)
328
- raise ::ArgumentError, "no block given" unless block_given?
352
+ raise ::ArgumentError, 'no block given' unless block_given?
329
353
  @signal.then(&block)
330
354
  end
331
355
 
@@ -351,7 +375,7 @@ module Cassandra
351
375
  # @raise [ArgumentError] if no block given
352
376
  # @return [Cassandra::Future] a new future
353
377
  def fallback(&block)
354
- raise ::ArgumentError, "no block given" unless block_given?
378
+ raise ::ArgumentError, 'no block given' unless block_given?
355
379
  @signal.fallback(&block)
356
380
  end
357
381
 
@@ -372,7 +396,7 @@ module Cassandra
372
396
  @signal.get(timeout)
373
397
  end
374
398
 
375
- alias :join :get
399
+ alias join get
376
400
  end
377
401
 
378
402
  # @private
@@ -493,9 +517,7 @@ module Cassandra
493
517
  end
494
518
 
495
519
  def failure(error)
496
- unless error.is_a?(::Exception)
497
- raise ::ArgumentError, "error must be an exception, #{error.inspect} given"
498
- end
520
+ raise ::ArgumentError, "error must be an exception, #{error.inspect} given" unless error.is_a?(::Exception)
499
521
 
500
522
  return unless @state == :pending
501
523
 
@@ -507,12 +529,17 @@ module Cassandra
507
529
  @error = error
508
530
  @state = :broken
509
531
 
510
- listeners, @listeners = @listeners, nil
532
+ listeners = @listeners
533
+ @listeners = nil
511
534
  end
512
535
 
513
536
  @executor.execute do
514
537
  listeners.each do |listener|
515
- listener.failure(error) rescue nil
538
+ begin
539
+ listener.failure(error)
540
+ rescue
541
+ nil
542
+ end
516
543
  end
517
544
 
518
545
  synchronize do
@@ -534,12 +561,17 @@ module Cassandra
534
561
  @value = value
535
562
  @state = :fulfilled
536
563
 
537
- listeners, @listeners = @listeners, nil
564
+ listeners = @listeners
565
+ @listeners = nil
538
566
  end
539
567
 
540
568
  @executor.execute do
541
569
  listeners.each do |listener|
542
- listener.success(value) rescue nil
570
+ begin
571
+ listener.success(value)
572
+ rescue
573
+ nil
574
+ end
543
575
  end
544
576
 
545
577
  synchronize do
@@ -561,7 +593,7 @@ module Cassandra
561
593
  #
562
594
  # @return [Object] the value that the future has been resolved with
563
595
  def get(timeout = nil)
564
- timeout = timeout && Float(timeout)
596
+ timeout &&= Float(timeout)
565
597
 
566
598
  if timeout
567
599
  raise ::ArgumentError, "timeout cannot be negative, #{timeout.inspect} given" if timeout < 0
@@ -590,18 +622,18 @@ module Cassandra
590
622
 
591
623
  if @state == :pending
592
624
  total_wait = deadline - start
593
- raise Errors::TimeoutError, "Future did not complete within #{timeout.inspect} seconds. Wait time: #{total_wait.inspect}"
625
+ raise Errors::TimeoutError,
626
+ "Future did not complete within #{timeout.inspect} seconds. " \
627
+ "Wait time: #{total_wait.inspect}"
594
628
  end
595
629
  end
596
630
 
597
- if @state == :broken
598
- raise(@error, @error.message, @error.backtrace)
599
- end
631
+ raise(@error, @error.message, @error.backtrace) if @state == :broken
600
632
 
601
633
  @value
602
634
  end
603
635
 
604
- alias :join :get
636
+ alias join get
605
637
 
606
638
  def add_listener(listener)
607
639
  if @state == :pending
@@ -614,8 +646,16 @@ module Cassandra
614
646
  end
615
647
  end
616
648
 
617
- listener.success(@value) rescue nil if @state == :fulfilled
618
- listener.failure(@error) rescue nil if @state == :broken
649
+ begin
650
+ listener.success(@value)
651
+ rescue
652
+ nil
653
+ end if @state == :fulfilled
654
+ begin
655
+ listener.failure(@error)
656
+ rescue
657
+ nil
658
+ end if @state == :broken
619
659
 
620
660
  self
621
661
  end
@@ -630,7 +670,11 @@ module Cassandra
630
670
  end
631
671
  end
632
672
 
633
- yield(@value) rescue nil if @state == :fulfilled
673
+ begin
674
+ yield(@value)
675
+ rescue
676
+ nil
677
+ end if @state == :fulfilled
634
678
 
635
679
  self
636
680
  end
@@ -645,7 +689,11 @@ module Cassandra
645
689
  end
646
690
  end
647
691
 
648
- yield(@error) rescue nil if @state == :broken
692
+ begin
693
+ yield(@error)
694
+ rescue
695
+ nil
696
+ end if @state == :broken
649
697
 
650
698
  self
651
699
  end
@@ -660,7 +708,11 @@ module Cassandra
660
708
  end
661
709
  end
662
710
 
663
- yield(@value, @error) rescue nil
711
+ begin
712
+ yield(@value, @error)
713
+ rescue
714
+ nil
715
+ end
664
716
 
665
717
  self
666
718
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -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,9 +37,25 @@ 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
- def initialize(ip, id = nil, rack = nil, datacenter = nil, release_version = nil, tokens = EMPTY_LIST, status = :up)
50
+ def initialize(ip,
51
+ id = nil,
52
+ rack = nil,
53
+ datacenter = nil,
54
+ release_version = nil,
55
+ tokens = EMPTY_LIST,
56
+ status = :up,
57
+ broadcast_address = nil,
58
+ listen_address = nil)
43
59
  @ip = ip
44
60
  @id = id
45
61
  @rack = rack
@@ -47,6 +63,10 @@ module Cassandra
47
63
  @release_version = release_version
48
64
  @tokens = tokens
49
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
50
70
  end
51
71
 
52
72
  # @return [Boolean] whether this host's status is `:up`
@@ -72,11 +92,11 @@ module Cassandra
72
92
  def eql?(other)
73
93
  other.eql?(@ip)
74
94
  end
75
- alias :== :eql?
95
+ alias == eql?
76
96
 
77
97
  # @private
78
98
  def inspect
79
- "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @ip=#{@ip}>"
99
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} @ip=#{@ip}>"
80
100
  end
81
101
  end
82
102
  end
@@ -0,0 +1,118 @@
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
+ @options = options.freeze
43
+
44
+ # Target is a bit tricky; it may be an escaped name or not
45
+ # depending on C* version. Unify to be unescaped since a user
46
+ # who wants to know the target would want the bare column name.
47
+
48
+ @target = if target[0] == '"'
49
+ target[1..-2]
50
+ else
51
+ target
52
+ end.freeze
53
+ end
54
+
55
+ # @return [Boolean] whether or not this index uses a custom class.
56
+ def custom_index?
57
+ !@options['class_name'].nil?
58
+ end
59
+
60
+ # @return [String] name of the index class if this is a custom index; nil otherwise.
61
+ def custom_class_name
62
+ @options['class_name']
63
+ end
64
+
65
+ # @return [String] a cql representation of this table
66
+ def to_cql
67
+ keyspace_name = Util.escape_name(@table.keyspace.name)
68
+ table_name = Util.escape_name(@table.name)
69
+ index_name = Util.escape_name(@name)
70
+
71
+ # Target is interesting in that it's not necessarily a column name,
72
+ # so we can't simply escape it. If it contains a paren, we take it as is,
73
+ # otherwise assume it's a column name and escape accordingly.
74
+ escaped_target = @target.include?('(') ? @target : Util.escape_name(@target)
75
+
76
+ if custom_index?
77
+ "CREATE CUSTOM INDEX #{index_name} ON #{keyspace_name}.#{table_name} (#{escaped_target}) " \
78
+ "USING '#{@options['class_name']}'#{options_cql};"
79
+ else
80
+ "CREATE INDEX #{index_name} ON #{keyspace_name}.#{table_name} (#{escaped_target});"
81
+ end
82
+ end
83
+
84
+ # @private
85
+ def eql?(other)
86
+ other.is_a?(Index) &&
87
+ @table == other.table &&
88
+ @name == other.name &&
89
+ @kind == other.kind &&
90
+ @target == other.target &&
91
+ @options == other.options
92
+ end
93
+ alias == eql?
94
+
95
+ # @private
96
+ def inspect
97
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
98
+ "@name=#{@name.inspect} @table=#{@table.inspect} @kind=#{@kind.inspect} @target=#{@target.inspect}>"
99
+ end
100
+
101
+ private
102
+
103
+ def options_cql
104
+ # exclude 'class_name', 'target' keys
105
+ filtered_options = @options.reject do |key, _|
106
+ key == 'class_name' || key == 'target'
107
+ end
108
+ return '' if filtered_options.empty?
109
+
110
+ result = ' WITH OPTIONS = {'
111
+ result << filtered_options.map do |key, value|
112
+ "'#{key}': '#{value}'"
113
+ end.join(', ')
114
+ result << '}'
115
+ result
116
+ end
117
+ end
118
+ end