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

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 (131) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +90 -38
  3. data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
  4. data/lib/cassandra.rb +327 -130
  5. data/lib/cassandra/address_resolution.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  7. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  8. data/lib/cassandra/aggregate.rb +21 -7
  9. data/lib/cassandra/argument.rb +2 -2
  10. data/lib/cassandra/auth.rb +4 -4
  11. data/lib/cassandra/auth/providers.rb +1 -1
  12. data/lib/cassandra/auth/providers/password.rb +9 -5
  13. data/lib/cassandra/cassandra_logger.rb +80 -0
  14. data/lib/cassandra/cluster.rb +38 -9
  15. data/lib/cassandra/cluster/client.rb +801 -205
  16. data/lib/cassandra/cluster/connection_pool.rb +2 -2
  17. data/lib/cassandra/cluster/connector.rb +74 -25
  18. data/lib/cassandra/cluster/control_connection.rb +217 -82
  19. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  20. data/lib/cassandra/cluster/metadata.rb +12 -4
  21. data/lib/cassandra/cluster/options.rb +60 -11
  22. data/lib/cassandra/cluster/registry.rb +69 -16
  23. data/lib/cassandra/cluster/schema.rb +25 -7
  24. data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
  25. data/lib/cassandra/cluster/schema/fetchers.rb +263 -106
  26. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +41 -36
  27. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  28. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +3 -3
  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 +3 -3
  36. data/lib/cassandra/compression.rb +1 -1
  37. data/lib/cassandra/compression/compressors/lz4.rb +4 -3
  38. data/lib/cassandra/compression/compressors/snappy.rb +4 -3
  39. data/lib/cassandra/driver.rb +103 -41
  40. data/lib/cassandra/errors.rb +265 -30
  41. data/lib/cassandra/execution/info.rb +16 -5
  42. data/lib/cassandra/execution/options.rb +99 -54
  43. data/lib/cassandra/execution/trace.rb +16 -9
  44. data/lib/cassandra/executors.rb +1 -1
  45. data/lib/cassandra/function.rb +19 -13
  46. data/lib/cassandra/function_collection.rb +85 -0
  47. data/lib/cassandra/future.rb +106 -48
  48. data/lib/cassandra/host.rb +10 -4
  49. data/lib/cassandra/keyspace.rb +90 -33
  50. data/lib/cassandra/listener.rb +1 -1
  51. data/lib/cassandra/load_balancing.rb +2 -2
  52. data/lib/cassandra/load_balancing/policies.rb +1 -1
  53. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +18 -18
  54. data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
  55. data/lib/cassandra/load_balancing/policies/token_aware.rb +15 -13
  56. data/lib/cassandra/load_balancing/policies/white_list.rb +11 -5
  57. data/lib/cassandra/null_logger.rb +27 -6
  58. data/lib/cassandra/protocol.rb +1 -1
  59. data/lib/cassandra/protocol/coder.rb +78 -39
  60. data/lib/cassandra/protocol/cql_byte_buffer.rb +50 -33
  61. data/lib/cassandra/protocol/cql_protocol_handler.rb +44 -45
  62. data/lib/cassandra/protocol/request.rb +2 -2
  63. data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
  64. data/lib/cassandra/protocol/requests/batch_request.rb +16 -7
  65. data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
  66. data/lib/cassandra/protocol/requests/execute_request.rb +41 -20
  67. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  68. data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
  69. data/lib/cassandra/protocol/requests/query_request.rb +27 -22
  70. data/lib/cassandra/protocol/requests/register_request.rb +2 -2
  71. data/lib/cassandra/protocol/requests/startup_request.rb +6 -4
  72. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  73. data/lib/cassandra/protocol/response.rb +2 -2
  74. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
  75. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
  76. data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
  77. data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
  78. data/lib/cassandra/protocol/responses/error_response.rb +101 -13
  79. data/lib/cassandra/protocol/responses/event_response.rb +1 -1
  80. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
  81. data/lib/cassandra/protocol/responses/prepared_result_response.rb +11 -5
  82. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
  83. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
  84. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
  85. data/lib/cassandra/protocol/responses/ready_response.rb +3 -3
  86. data/lib/cassandra/protocol/responses/result_response.rb +4 -2
  87. data/lib/cassandra/protocol/responses/rows_result_response.rb +5 -3
  88. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +5 -4
  89. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +16 -9
  90. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
  91. data/lib/cassandra/protocol/responses/status_change_event_response.rb +2 -2
  92. data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
  93. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
  94. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
  95. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
  96. data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
  97. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
  98. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
  99. data/lib/cassandra/protocol/v1.rb +101 -36
  100. data/lib/cassandra/protocol/v3.rb +124 -51
  101. data/lib/cassandra/protocol/v4.rb +172 -68
  102. data/lib/cassandra/reconnection.rb +1 -1
  103. data/lib/cassandra/reconnection/policies.rb +1 -1
  104. data/lib/cassandra/reconnection/policies/constant.rb +2 -4
  105. data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
  106. data/lib/cassandra/result.rb +53 -19
  107. data/lib/cassandra/retry.rb +8 -8
  108. data/lib/cassandra/retry/policies.rb +1 -1
  109. data/lib/cassandra/retry/policies/default.rb +1 -1
  110. data/lib/cassandra/retry/policies/downgrading_consistency.rb +7 -3
  111. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  112. data/lib/cassandra/session.rb +22 -16
  113. data/lib/cassandra/statement.rb +1 -1
  114. data/lib/cassandra/statements.rb +1 -1
  115. data/lib/cassandra/statements/batch.rb +16 -10
  116. data/lib/cassandra/statements/bound.rb +10 -3
  117. data/lib/cassandra/statements/prepared.rb +59 -15
  118. data/lib/cassandra/statements/simple.rb +23 -10
  119. data/lib/cassandra/statements/void.rb +1 -1
  120. data/lib/cassandra/table.rb +79 -30
  121. data/lib/cassandra/time.rb +11 -6
  122. data/lib/cassandra/time_uuid.rb +7 -7
  123. data/lib/cassandra/tuple.rb +16 -8
  124. data/lib/cassandra/types.rb +20 -9
  125. data/lib/cassandra/udt.rb +32 -36
  126. data/lib/cassandra/util.rb +20 -13
  127. data/lib/cassandra/uuid.rb +22 -15
  128. data/lib/cassandra/uuid/generator.rb +7 -5
  129. data/lib/cassandra/version.rb +2 -2
  130. data/lib/datastax/cassandra.rb +1 -1
  131. metadata +5 -3
@@ -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.
@@ -38,11 +38,11 @@ module Cassandra
38
38
  # @return [String] paging state
39
39
  #
40
40
  # @note Although this feature exists to allow web applications to store
41
- # paging state in an [HTTP cookie](http://en.wikipedia.org/wiki/HTTP_cookie), **it is not safe to
42
- # expose without encrypting or otherwise securing it**. Paging state
43
- # contains information internal to the Apache Cassandra cluster, such as
44
- # partition key and data. Additionally, if a paging state is sent with CQL
45
- # statement, different from the original, the behavior of Cassandra is
41
+ # paging state in an [HTTP cookie](http://en.wikipedia.org/wiki/HTTP_cookie),
42
+ # **it is not safe to expose without encrypting or otherwise securing it**.
43
+ # Paging state contains information internal to the Apache Cassandra cluster,
44
+ # such as partition key and data. Additionally, if a paging state is sent with
45
+ # CQL statement, different from the original, the behavior of Cassandra is
46
46
  # undefined and will likely cause a server process of the coordinator of
47
47
  # such request to abort.
48
48
  #
@@ -53,7 +53,7 @@ module Cassandra
53
53
  # string and byte buffers.
54
54
  #
55
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/features/custom_payloads/#enabling-custom-payloads-on-c-nodes Enabling custom payloads on Cassandra nodes.
56
+ # @see https://datastax.github.io/java-driver/manual/custom_payloads/#enabling-custom-payloads-on-c-nodes Enabling custom payloads on Cassandra nodes.
57
57
  #
58
58
  # @example Sending a custom payload
59
59
  # result = session.execute(payload: {
@@ -63,7 +63,10 @@ module Cassandra
63
63
  attr_reader :payload
64
64
 
65
65
  # @private
66
- def initialize(options)
66
+ # @param options [Hash] execution options to validate and encapsulate
67
+ # @param trusted_options [Options] (optional) base Execution::Options from which
68
+ # to create this new Options object.
69
+ def initialize(options, trusted_options = nil)
67
70
  consistency = options[:consistency]
68
71
  page_size = options[:page_size]
69
72
  trace = options[:trace]
@@ -75,61 +78,114 @@ module Cassandra
75
78
  idempotent = options[:idempotent]
76
79
  payload = options[:payload]
77
80
 
78
- Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
81
+ # consistency is a required attribute of an Options object. If we are creating
82
+ # an Options object from scratch (e.g. no trusted_options as base) validate the
83
+ # given consistency value (even if nil). Otherwise we're overlaying and only
84
+ # validate the consistency option if given.
85
+ if trusted_options.nil? || !consistency.nil?
86
+ Util.assert_one_of(CONSISTENCIES, consistency) do
87
+ ":consistency must be one of #{CONSISTENCIES.inspect}, " \
88
+ "#{consistency.inspect} given"
89
+ end
90
+ end
79
91
 
80
92
  unless serial_consistency.nil?
81
- Util.assert_one_of(SERIAL_CONSISTENCIES, serial_consistency) { ":serial_consistency must be one of #{SERIAL_CONSISTENCIES.inspect}, #{serial_consistency.inspect} given" }
93
+ Util.assert_one_of(SERIAL_CONSISTENCIES, serial_consistency) do
94
+ ":serial_consistency must be one of #{SERIAL_CONSISTENCIES.inspect}, " \
95
+ "#{serial_consistency.inspect} given"
96
+ end
82
97
  end
83
98
 
84
99
  unless page_size.nil?
85
100
  page_size = Integer(page_size)
86
- Util.assert(page_size > 0) { ":page_size must be a positive integer, #{page_size.inspect} given" }
101
+ Util.assert(page_size > 0) do
102
+ ":page_size must be a positive integer, #{page_size.inspect} given"
103
+ end
87
104
  end
88
105
 
89
106
  unless timeout.nil?
90
- Util.assert_instance_of(::Numeric, timeout) { ":timeout must be a number of seconds, #{timeout} given" }
107
+ Util.assert_instance_of(::Numeric, timeout) do
108
+ ":timeout must be a number of seconds, #{timeout} given"
109
+ end
91
110
  Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
92
111
  end
93
112
 
94
113
  unless paging_state.nil?
95
114
  paging_state = String(paging_state)
96
- Util.assert_not_empty(paging_state) { ":paging_state must not be empty" }
97
- Util.assert(!page_size.nil?) { ":page_size is required when :paging_state is given" }
115
+ Util.assert_not_empty(paging_state) { ':paging_state must not be empty' }
116
+
117
+ # We require page_size in either the new options or trusted options.
118
+ Util.assert(!page_size.nil? ||
119
+ !(trusted_options.nil? || trusted_options.page_size.nil?)) do
120
+ ':page_size is required when :paging_state is given'
121
+ end
98
122
  end
99
123
 
100
- if arguments.nil?
124
+ # :arguments defaults to empty-list, but we want to delegate to trusted_options
125
+ # if it's set. So the logic is as follows:
126
+ # If an arguments option was given, validate and use it regardless of anything
127
+ # else.
128
+ # Otherwise, if we have trusted_options, leave arguments nil for now so as not
129
+ # to override trusted_options. Finally, if we don't have an arguments option
130
+ # nor do we have trusted_options, fall back to the default empty-list.
131
+ #
132
+ # :type_hints works exactly the same way.
133
+ if !arguments.nil?
134
+ Util.assert_instance_of_one_of([::Array, ::Hash], arguments) do
135
+ ":arguments must be an Array or a Hash, #{arguments.inspect} given"
136
+ end
137
+ elsif trusted_options.nil?
101
138
  arguments = EMPTY_LIST
102
- else
103
- Util.assert_instance_of_one_of([::Array, ::Hash], arguments) { ":arguments must be an Array or a Hash, #{arguments.inspect} given" }
104
139
  end
105
140
 
106
- if type_hints.nil?
141
+ if !type_hints.nil?
142
+ Util.assert_instance_of_one_of([::Array, ::Hash], type_hints) do
143
+ ":type_hints must be an Array or a Hash, #{type_hints.inspect} given"
144
+ end
145
+ elsif trusted_options.nil?
107
146
  type_hints = EMPTY_LIST
108
- else
109
- Util.assert_instance_of_one_of([::Array, ::Hash], type_hints) { ":type_hints must be an Array or a Hash, #{type_hints.inspect} given" }
110
147
  end
111
148
 
112
149
  unless payload.nil?
113
- Util.assert_instance_of(::Hash, payload) { ":payload must be a Hash" }
114
- Util.assert_not_empty(payload) { ":payload must not be empty" }
115
- Util.assert(payload.size <= 65535) { ":payload cannot contain more than 65535 key/value pairs" }
116
-
117
- payload = payload.each_with_object(::Hash.new) do |(key, value), payload|
118
- payload[String(key)] = String(value)
119
- end
150
+ Util.assert_instance_of(::Hash, payload) { ':payload must be a Hash' }
151
+ Util.assert_not_empty(payload) { ':payload must not be empty' }
152
+ Util.assert(payload.size <= 65535) do
153
+ ':payload cannot contain more than 65535 key/value pairs'
154
+ end
155
+
156
+ payload = payload.each_with_object(::Hash.new) do |(key, value), p|
157
+ p[String(key)] = String(value)
158
+ end
120
159
  payload.freeze
121
160
  end
122
161
 
123
- @consistency = consistency
124
- @page_size = page_size
125
- @trace = !!trace
126
- @timeout = timeout
127
- @serial_consistency = serial_consistency
128
- @paging_state = paging_state
129
- @arguments = arguments
130
- @type_hints = type_hints
131
- @idempotent = !!idempotent
132
- @payload = payload
162
+ # Ok, validation is done. Time to save off all our values in our instance vars,
163
+ # merging in values from trusted_options if it's set. To keep things readable,
164
+ # we just put this into two branches of an if-else.
165
+
166
+ if trusted_options.nil?
167
+ @consistency = consistency
168
+ @page_size = page_size
169
+ @trace = !!trace
170
+ @timeout = timeout
171
+ @serial_consistency = serial_consistency
172
+ @arguments = arguments
173
+ @type_hints = type_hints
174
+ else
175
+ @consistency = consistency || trusted_options.consistency
176
+ @page_size = page_size || trusted_options.page_size
177
+ @trace = trace.nil? ? trusted_options.trace? : !!trace
178
+ @timeout = timeout || trusted_options.timeout
179
+ @serial_consistency = serial_consistency || trusted_options.serial_consistency
180
+ @arguments = arguments || trusted_options.arguments
181
+ @type_hints = type_hints || trusted_options.type_hints
182
+ end
183
+
184
+ # The following fields are *not* inherited from trusted_options, so we always
185
+ # rely on the options we were given.
186
+ @paging_state = paging_state
187
+ @idempotent = !!idempotent
188
+ @payload = payload
133
189
  end
134
190
 
135
191
  # @return [Boolean] whether request tracing was enabled
@@ -154,30 +210,19 @@ module Cassandra
154
210
  other.arguments == @arguments &&
155
211
  other.type_hints == @type_hints
156
212
  end
157
- alias :== :eql?
213
+ alias == eql?
158
214
 
159
215
  # @private
160
216
  def override(*options)
161
- merged = options.unshift(to_h).inject do |base, opts|
217
+ merged = options.unshift({}).inject do |base, opts|
162
218
  next base unless opts
163
- Util.assert_instance_of(::Hash, opts) { "options must be a Hash, #{options.inspect} given" }
219
+ Util.assert_instance_of(::Hash, opts) do
220
+ "options must be a Hash, #{options.inspect} given"
221
+ end
164
222
  base.merge!(opts)
165
223
  end
166
224
 
167
- Options.new(merged)
168
- end
169
-
170
- # @private
171
- def to_h
172
- {
173
- :consistency => @consistency,
174
- :page_size => @page_size,
175
- :trace => @trace,
176
- :timeout => @timeout,
177
- :serial_consistency => @serial_consistency,
178
- :arguments => @arguments || EMPTY_LIST,
179
- :type_hints => @type_hints || EMPTY_LIST
180
- }
225
+ Options.new(merged, self)
181
226
  end
182
227
  end
183
228
  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.
@@ -44,7 +44,7 @@ module Cassandra
44
44
  other == @id
45
45
  end
46
46
 
47
- alias :eql? :==
47
+ alias eql? ==
48
48
  end
49
49
 
50
50
  include MonitorMixin
@@ -124,15 +124,15 @@ module Cassandra
124
124
 
125
125
  # @private
126
126
  def inspect
127
- "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @id=#{@id.inspect}>"
127
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} @id=#{@id.inspect}>"
128
128
  end
129
129
 
130
130
  private
131
131
 
132
132
  # @private
133
- SELECT_SESSION = "SELECT * FROM system_traces.sessions WHERE session_id = %s"
133
+ SELECT_SESSION = 'SELECT * FROM system_traces.sessions WHERE session_id = %s'.freeze
134
134
  # @private
135
- SELECT_EVENTS = "SELECT * FROM system_traces.events WHERE session_id = %s"
135
+ SELECT_EVENTS = 'SELECT * FROM system_traces.events WHERE session_id = %s'.freeze
136
136
 
137
137
  # @private
138
138
  def load
@@ -140,11 +140,13 @@ module Cassandra
140
140
  return if @loaded
141
141
 
142
142
  attempt = 1
143
- data = @client.query(Statements::Simple.new(SELECT_SESSION % @id), VOID_OPTIONS).get.first
143
+ data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
144
+ VOID_OPTIONS).get.first
144
145
 
145
146
  while data.nil? && attempt <= 5
146
147
  sleep(attempt * 0.4)
147
- data = @client.query(Statements::Simple.new(SELECT_SESSION % @id), VOID_OPTIONS).get.first
148
+ data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
149
+ VOID_OPTIONS).get.first
148
150
  break if data
149
151
  attempt += 1
150
152
  end
@@ -170,8 +172,13 @@ module Cassandra
170
172
 
171
173
  @events = []
172
174
 
173
- @client.query(Statements::Simple.new(SELECT_EVENTS % @id), VOID_OPTIONS).get.each do |row|
174
- @events << Event.new(row['event_id'], row['activity'], row['source'], row['source_elapsed'], row['thread'])
175
+ @client.query(Statements::Simple.new(SELECT_EVENTS % @id),
176
+ VOID_OPTIONS).get.each do |row|
177
+ @events << Event.new(row['event_id'],
178
+ row['activity'],
179
+ row['source'],
180
+ row['source_elapsed'],
181
+ row['thread'])
175
182
  end
176
183
 
177
184
  @events.freeze
@@ -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.
@@ -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.
@@ -57,7 +57,7 @@ module Cassandra
57
57
  # @param name [String] argument name
58
58
  # @return [Boolean] whether this function has a given argument
59
59
  def has_argument?(name)
60
- @arguments_hash.has_key?(name)
60
+ @arguments_hash.key?(name)
61
61
  end
62
62
 
63
63
  # @param name [String] argument name
@@ -82,12 +82,12 @@ module Cassandra
82
82
  @arguments.dup
83
83
  end
84
84
  end
85
- alias :arguments :each_argument
85
+ alias arguments each_argument
86
86
 
87
87
  # Get the list of argument types for this function.
88
88
  # @return [Array<Cassandra::Type>] a list of argument types.
89
89
  def argument_types
90
- @arguments.map { |argument| argument.type }
90
+ @arguments.map(&:type)
91
91
  end
92
92
 
93
93
  # @private
@@ -101,7 +101,7 @@ module Cassandra
101
101
  @body == other.body && \
102
102
  @called_on_null == other.called_on_null?
103
103
  end
104
- alias :== :eql?
104
+ alias == eql?
105
105
 
106
106
  # @private
107
107
  def hash
@@ -120,7 +120,13 @@ module Cassandra
120
120
 
121
121
  # @private
122
122
  def inspect
123
- "#<Cassandra::Function:0x#{self.object_id.to_s(16)} @keyspace=#{@keyspace.inspect}, @name=#{@name.inspect}, @language=#{@language.inspect}, @type=#{@type.inspect}, @arguments=#{@arguments.inspect} @body=#{@body.inspect}>"
123
+ "#<Cassandra::Function:0x#{object_id.to_s(16)} " \
124
+ "@keyspace=#{@keyspace.inspect}, " \
125
+ "@name=#{@name.inspect}, " \
126
+ "@language=#{@language.inspect}, " \
127
+ "@type=#{@type.inspect}, " \
128
+ "@arguments=#{@arguments.inspect} " \
129
+ "@body=#{@body.inspect}>"
124
130
  end
125
131
 
126
132
  # @return [String] a cql representation of this function
@@ -135,16 +141,16 @@ module Cassandra
135
141
  end
136
142
  cql << "#{argument.name} #{argument.type}"
137
143
  end
138
- cql << ")"
139
- if @called_on_null
140
- cql << "\n CALLED ON NULL INPUT"
141
- else
142
- cql << "\n RETURNS NULL ON NULL INPUT"
143
- end
144
+ cql << ')'
145
+ cql << if @called_on_null
146
+ "\n CALLED ON NULL INPUT"
147
+ else
148
+ "\n RETURNS NULL ON NULL INPUT"
149
+ end
144
150
  cql << "\n RETURNS #{@type}"
145
151
  cql << "\n LANGUAGE #{@language}"
146
152
  cql << "\n AS $$#{@body}$$"
147
- cql << ";"
153
+ cql << ';'
148
154
  end
149
155
  end
150
156
  end
@@ -0,0 +1,85 @@
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
+ # @private
21
+ # This class encapsulates a collection of functions or aggregates.
22
+ # Really used internally, so it should not be documented.
23
+ class FunctionCollection
24
+ def initialize
25
+ @function_hash = {}
26
+ end
27
+
28
+ # Get the Function or Aggregate with the given name and argument-types.
29
+ # @param name [String] the name of the function/aggregate.
30
+ # @param argument_types [Array<Cassandra::Type>] list of argument-types.
31
+ # @return [Cassandra::Function] or [Cassandra::Aggregate] if found;
32
+ # nil otherwise.
33
+ def get(name, argument_types)
34
+ @function_hash[[name, argument_types]]
35
+ end
36
+
37
+ def add_or_update(function)
38
+ @function_hash[[function.name, function.argument_types]] = function
39
+ end
40
+
41
+ def delete(name, argument_types)
42
+ @function_hash.delete([name, argument_types])
43
+ end
44
+
45
+ # @return [Boolean] whether this FunctionCollection is equal to the other
46
+ def eql?(other)
47
+ other.is_a?(FunctionCollection) &&
48
+ @function_hash == other.raw_functions
49
+ end
50
+ alias == eql?
51
+
52
+ def hash
53
+ @function_hash.hash
54
+ end
55
+
56
+ # Yield or enumerate each function defined in this collection
57
+ # @overload each_function
58
+ # @yieldparam function [Cassandra::Function or Cassandra::Aggregate]
59
+ # current function or aggregate
60
+ # @return [Cassandra::FunctionCollection] self
61
+ # @overload each_function
62
+ # @return [Array<Cassandra::Function> or Array<Cassandra::Aggregate>]
63
+ # a list of functions or aggregates.
64
+ def each_function(&block)
65
+ if block_given?
66
+ @function_hash.each_value(&block)
67
+ self
68
+ else
69
+ @function_hash.values
70
+ end
71
+ end
72
+ alias functions each_function
73
+
74
+ def inspect
75
+ "#<Cassandra::FunctionCollection:0x#{object_id.to_s(16)} " \
76
+ "@function_hash=#{@function_hash.inspect}>"
77
+ end
78
+
79
+ protected
80
+
81
+ def raw_functions
82
+ @function_hash
83
+ end
84
+ end
85
+ end