yugabyte-ycql-driver 3.2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/README.md +242 -0
  4. data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
  5. data/ext/cassandra_murmur3/extconf.rb +2 -0
  6. data/lib/cassandra/address_resolution.rb +36 -0
  7. data/lib/cassandra/address_resolution/policies.rb +2 -0
  8. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
  9. data/lib/cassandra/address_resolution/policies/none.rb +35 -0
  10. data/lib/cassandra/aggregate.rb +123 -0
  11. data/lib/cassandra/argument.rb +51 -0
  12. data/lib/cassandra/attr_boolean.rb +33 -0
  13. data/lib/cassandra/auth.rb +100 -0
  14. data/lib/cassandra/auth/providers.rb +17 -0
  15. data/lib/cassandra/auth/providers/password.rb +65 -0
  16. data/lib/cassandra/cassandra_logger.rb +80 -0
  17. data/lib/cassandra/cluster.rb +331 -0
  18. data/lib/cassandra/cluster/client.rb +1612 -0
  19. data/lib/cassandra/cluster/connection_pool.rb +78 -0
  20. data/lib/cassandra/cluster/connector.rb +372 -0
  21. data/lib/cassandra/cluster/control_connection.rb +962 -0
  22. data/lib/cassandra/cluster/failed_connection.rb +35 -0
  23. data/lib/cassandra/cluster/metadata.rb +142 -0
  24. data/lib/cassandra/cluster/options.rb +145 -0
  25. data/lib/cassandra/cluster/registry.rb +284 -0
  26. data/lib/cassandra/cluster/schema.rb +405 -0
  27. data/lib/cassandra/cluster/schema/cql_type_parser.rb +112 -0
  28. data/lib/cassandra/cluster/schema/fetchers.rb +1627 -0
  29. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +175 -0
  30. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  31. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +45 -0
  32. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  33. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  34. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  35. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +102 -0
  36. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  37. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  38. data/lib/cassandra/column.rb +66 -0
  39. data/lib/cassandra/column_container.rb +326 -0
  40. data/lib/cassandra/compression.rb +69 -0
  41. data/lib/cassandra/compression/compressors/lz4.rb +73 -0
  42. data/lib/cassandra/compression/compressors/snappy.rb +69 -0
  43. data/lib/cassandra/custom_data.rb +53 -0
  44. data/lib/cassandra/driver.rb +260 -0
  45. data/lib/cassandra/errors.rb +784 -0
  46. data/lib/cassandra/execution/info.rb +69 -0
  47. data/lib/cassandra/execution/options.rb +267 -0
  48. data/lib/cassandra/execution/profile.rb +153 -0
  49. data/lib/cassandra/execution/profile_manager.rb +71 -0
  50. data/lib/cassandra/execution/trace.rb +192 -0
  51. data/lib/cassandra/executors.rb +113 -0
  52. data/lib/cassandra/function.rb +156 -0
  53. data/lib/cassandra/function_collection.rb +85 -0
  54. data/lib/cassandra/future.rb +794 -0
  55. data/lib/cassandra/host.rb +102 -0
  56. data/lib/cassandra/index.rb +118 -0
  57. data/lib/cassandra/keyspace.rb +473 -0
  58. data/lib/cassandra/listener.rb +87 -0
  59. data/lib/cassandra/load_balancing.rb +121 -0
  60. data/lib/cassandra/load_balancing/policies.rb +20 -0
  61. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +172 -0
  62. data/lib/cassandra/load_balancing/policies/round_robin.rb +141 -0
  63. data/lib/cassandra/load_balancing/policies/token_aware.rb +149 -0
  64. data/lib/cassandra/load_balancing/policies/white_list.rb +100 -0
  65. data/lib/cassandra/materialized_view.rb +92 -0
  66. data/lib/cassandra/null_logger.rb +56 -0
  67. data/lib/cassandra/protocol.rb +102 -0
  68. data/lib/cassandra/protocol/coder.rb +1085 -0
  69. data/lib/cassandra/protocol/cql_byte_buffer.rb +418 -0
  70. data/lib/cassandra/protocol/cql_protocol_handler.rb +448 -0
  71. data/lib/cassandra/protocol/request.rb +41 -0
  72. data/lib/cassandra/protocol/requests/auth_response_request.rb +51 -0
  73. data/lib/cassandra/protocol/requests/batch_request.rb +117 -0
  74. data/lib/cassandra/protocol/requests/credentials_request.rb +51 -0
  75. data/lib/cassandra/protocol/requests/execute_request.rb +122 -0
  76. data/lib/cassandra/protocol/requests/options_request.rb +39 -0
  77. data/lib/cassandra/protocol/requests/prepare_request.rb +59 -0
  78. data/lib/cassandra/protocol/requests/query_request.rb +112 -0
  79. data/lib/cassandra/protocol/requests/register_request.rb +38 -0
  80. data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
  81. data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
  82. data/lib/cassandra/protocol/response.rb +28 -0
  83. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +50 -0
  84. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +36 -0
  85. data/lib/cassandra/protocol/responses/auth_success_response.rb +36 -0
  86. data/lib/cassandra/protocol/responses/authenticate_response.rb +36 -0
  87. data/lib/cassandra/protocol/responses/error_response.rb +142 -0
  88. data/lib/cassandra/protocol/responses/event_response.rb +30 -0
  89. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +52 -0
  90. data/lib/cassandra/protocol/responses/prepared_result_response.rb +62 -0
  91. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +59 -0
  92. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +71 -0
  93. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +61 -0
  94. data/lib/cassandra/protocol/responses/ready_response.rb +43 -0
  95. data/lib/cassandra/protocol/responses/result_response.rb +42 -0
  96. data/lib/cassandra/protocol/responses/rows_result_response.rb +39 -0
  97. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +73 -0
  98. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +70 -0
  99. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +37 -0
  100. data/lib/cassandra/protocol/responses/status_change_event_response.rb +39 -0
  101. data/lib/cassandra/protocol/responses/supported_response.rb +36 -0
  102. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +33 -0
  103. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +58 -0
  104. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +48 -0
  105. data/lib/cassandra/protocol/responses/void_result_response.rb +34 -0
  106. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +73 -0
  107. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +63 -0
  108. data/lib/cassandra/protocol/v1.rb +326 -0
  109. data/lib/cassandra/protocol/v3.rb +358 -0
  110. data/lib/cassandra/protocol/v4.rb +478 -0
  111. data/lib/cassandra/reconnection.rb +49 -0
  112. data/lib/cassandra/reconnection/policies.rb +20 -0
  113. data/lib/cassandra/reconnection/policies/constant.rb +46 -0
  114. data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
  115. data/lib/cassandra/result.rb +276 -0
  116. data/lib/cassandra/retry.rb +154 -0
  117. data/lib/cassandra/retry/policies.rb +21 -0
  118. data/lib/cassandra/retry/policies/default.rb +53 -0
  119. data/lib/cassandra/retry/policies/downgrading_consistency.rb +73 -0
  120. data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
  121. data/lib/cassandra/session.rb +270 -0
  122. data/lib/cassandra/statement.rb +32 -0
  123. data/lib/cassandra/statements.rb +23 -0
  124. data/lib/cassandra/statements/batch.rb +146 -0
  125. data/lib/cassandra/statements/bound.rb +65 -0
  126. data/lib/cassandra/statements/prepared.rb +235 -0
  127. data/lib/cassandra/statements/simple.rb +118 -0
  128. data/lib/cassandra/statements/void.rb +38 -0
  129. data/lib/cassandra/table.rb +240 -0
  130. data/lib/cassandra/time.rb +103 -0
  131. data/lib/cassandra/time_uuid.rb +78 -0
  132. data/lib/cassandra/timestamp_generator.rb +37 -0
  133. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  134. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  135. data/lib/cassandra/trigger.rb +67 -0
  136. data/lib/cassandra/tuple.rb +131 -0
  137. data/lib/cassandra/types.rb +1704 -0
  138. data/lib/cassandra/udt.rb +443 -0
  139. data/lib/cassandra/util.rb +464 -0
  140. data/lib/cassandra/uuid.rb +110 -0
  141. data/lib/cassandra/uuid/generator.rb +212 -0
  142. data/lib/cassandra/version.rb +21 -0
  143. data/lib/datastax/cassandra.rb +47 -0
  144. data/lib/ycql.rb +842 -0
  145. metadata +243 -0
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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
+ module Statements
21
+ class Simple
22
+ include Statement
23
+
24
+ # @return [String] original cql used to prepare this statement
25
+ attr_reader :cql
26
+ # @return [Array<Object>] a list of positional parameters for the cql
27
+ attr_reader :params
28
+
29
+ # @private
30
+ attr_reader :params_types
31
+
32
+ # @private
33
+ attr_reader :params_names
34
+
35
+ # @param cql [String] a cql statement
36
+ # @param params [Array, Hash] (nil) positional or named arguments
37
+ # for the query
38
+ # @param type_hints [Array, Hash] (nil) positional or named types
39
+ # to override type guessing for the query
40
+ # @param idempotent [Boolean] (false) whether this statement can be
41
+ # safely retries on timeouts
42
+ #
43
+ # @note Positional arguments for simple statements are only supported
44
+ # starting with Apache Cassandra 2.0 and above.
45
+ #
46
+ # @note Named arguments for simple statements are only supported
47
+ # starting with Apache Cassandra 2.1 and above.
48
+ #
49
+ # @raise [ArgumentError] if cql statement given is not a String
50
+ def initialize(cql, params = nil, type_hints = nil, idempotent = false)
51
+ Util.assert_instance_of(::String, cql) do
52
+ "cql must be a string, #{cql.inspect} given"
53
+ end
54
+
55
+ params ||= EMPTY_LIST
56
+
57
+ if params.is_a?(::Hash)
58
+ params_names = []
59
+ params = params.each_with_object([]) do |(name, value), collector|
60
+ params_names << name
61
+ collector << value
62
+ end
63
+ if type_hints && !type_hints.empty?
64
+ Util.assert_instance_of(::Hash, type_hints) do
65
+ 'type_hints must be a Hash when using named params'
66
+ end
67
+ end
68
+ else
69
+ Util.assert_instance_of(::Array, params) do
70
+ "params must be an Array or a Hash, #{params.inspect} given"
71
+ end
72
+ params_names = EMPTY_LIST
73
+ end
74
+
75
+ type_hints ||= EMPTY_LIST
76
+
77
+ if type_hints.is_a?(::Hash)
78
+ type_hints = params_names.map {|name| type_hints[name] }
79
+ else
80
+ Util.assert_instance_of(::Array, type_hints) do
81
+ "type_hints must be an Array or a Hash, #{type_hints.inspect} given"
82
+ end
83
+ end
84
+
85
+ @cql = cql
86
+ @params = params
87
+ @params_types = params.each_with_index.map do |value, index|
88
+ (!type_hints.empty? && type_hints[index] && type_hints[index].is_a?(Type)) ?
89
+ type_hints[index] :
90
+ Util.guess_type(value)
91
+ end
92
+ @params_names = params_names
93
+ @idempotent = idempotent
94
+ end
95
+
96
+ # @private
97
+ def accept(client, options)
98
+ client.query(self, options)
99
+ end
100
+
101
+ # @return [String] a CLI-friendly simple statement representation
102
+ def inspect
103
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} @cql=#{@cql.inspect} " \
104
+ "@params=#{@params.inspect}>"
105
+ end
106
+
107
+ # @param other [Object, Cassandra::Statements::Simple] object to compare
108
+ # @return [Boolean] whether the statements are equal
109
+ def eql?(other)
110
+ other.is_a?(Simple) &&
111
+ @cql == other.cql &&
112
+ @params == other.params
113
+ end
114
+
115
+ alias == eql?
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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
+ module Statements
21
+ # This statement is passed to {Cassandra::LoadBalancing::Policy#plan} when
22
+ # establishing connections and preparing statements
23
+ class Void
24
+ include Statement
25
+
26
+ # @private
27
+ def accept(client, options)
28
+ nil
29
+ end
30
+
31
+ # Returns nothing
32
+ # @return [nil] there is no cql for the void statement
33
+ def cql
34
+ nil
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,240 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 table
21
+ # @see Cassandra::Keyspace#each_table
22
+ # @see Cassandra::Keyspace#table
23
+ class Table < ColumnContainer
24
+ # @return [Array<Symbol>] an array of order values (`:asc` or `:desc`) that apply to the
25
+ # `clustering_columns` array.
26
+ attr_reader :clustering_order
27
+
28
+ # @private
29
+ def initialize(keyspace,
30
+ name,
31
+ partition_key,
32
+ clustering_columns,
33
+ other_columns,
34
+ options,
35
+ clustering_order,
36
+ id)
37
+ super(keyspace, name, partition_key, clustering_columns, other_columns, options, id)
38
+ @clustering_order = clustering_order.freeze
39
+ @indexes = []
40
+ @indexes_hash = {}
41
+ @materialized_views = []
42
+ @materialized_views_hash = {}
43
+ @triggers = []
44
+ @triggers_hash = {}
45
+ end
46
+
47
+ # @param name [String] index name
48
+ # @return [Boolean] whether this table has a given index
49
+ def has_index?(name)
50
+ @indexes_hash.key?(name)
51
+ end
52
+
53
+ # @param name [String] index name
54
+ # @return [Cassandra::Index, nil] an index or nil
55
+ def index(name)
56
+ @indexes_hash[name]
57
+ end
58
+
59
+ # Yield or enumerate each index bound to this table
60
+ # @overload each_index
61
+ # @yieldparam index [Cassandra::Index] current index
62
+ # @return [Cassandra::Table] self
63
+ # @overload each_index
64
+ # @return [Array<Cassandra::Index>] a list of indexes
65
+ def each_index(&block)
66
+ if block_given?
67
+ @indexes.each(&block)
68
+ self
69
+ else
70
+ @indexes.freeze
71
+ end
72
+ end
73
+ alias indexes each_index
74
+
75
+ # @param name [String] trigger name
76
+ # @return [Boolean] whether this table has a given trigger
77
+ def has_trigger?(name)
78
+ @triggers_hash.key?(name)
79
+ end
80
+
81
+ # @param name [String] trigger name
82
+ # @return [Cassandra::Trigger, nil] a trigger or nil
83
+ def trigger(name)
84
+ @triggers_hash[name]
85
+ end
86
+
87
+ # Yield or enumerate each trigger bound to this table
88
+ # @overload each_trigger
89
+ # @yieldparam trigger [Cassandra::Index] current trigger
90
+ # @return [Cassandra::Table] self
91
+ # @overload each_trigger
92
+ # @return [Array<Cassandra::Trigger>] a list of triggers
93
+ def each_trigger(&block)
94
+ if block_given?
95
+ @triggers.each(&block)
96
+ self
97
+ else
98
+ @triggers.freeze
99
+ end
100
+ end
101
+ alias triggers each_trigger
102
+
103
+ # @param name [String] materialized view name
104
+ # @return [Boolean] whether this table has a given materialized view
105
+ def has_materialized_view?(name)
106
+ @materialized_views_hash.key?(name)
107
+ end
108
+
109
+ # @param name [String] materialized view name
110
+ # @return [Cassandra::MaterializedView, nil] a materialized view or nil
111
+ def materialized_view(name)
112
+ @materialized_views_hash[name]
113
+ end
114
+
115
+ # Yield or enumerate each materialized view bound to this table
116
+ # @overload each_materialized_view
117
+ # @yieldparam materialized_view [Cassandra::MaterializedView] current materialized view
118
+ # @return [Cassandra::Table] self
119
+ # @overload each_materialized_view
120
+ # @return [Array<Cassandra::MaterializedView>] a list of materialized views
121
+ def each_materialized_view(&block)
122
+ if block_given?
123
+ @materialized_views.each(&block)
124
+ self
125
+ else
126
+ @materialized_views.freeze
127
+ end
128
+ end
129
+ alias materialized_views each_materialized_view
130
+
131
+ # @return [String] a cql representation of this table
132
+ def to_cql
133
+ cql = "CREATE TABLE #{Util.escape_name(@keyspace.name)}.#{Util.escape_name(@name)} (\n"
134
+ primary_key = @partition_key.first.name if @partition_key.one? && @clustering_columns.empty?
135
+
136
+ first = true
137
+ @columns.each do |column|
138
+ if first
139
+ first = false
140
+ else
141
+ cql << ",\n"
142
+ end
143
+ cql << " #{Util.escape_name(column.name)} #{type_to_cql(column.type, column.frozen?)}"
144
+ cql << ' PRIMARY KEY' if primary_key && column.name == primary_key
145
+ end
146
+
147
+ unless primary_key
148
+ cql << ",\n PRIMARY KEY ("
149
+ if @partition_key.one?
150
+ cql << Util.escape_name(@partition_key.first.name)
151
+ else
152
+ cql << '('
153
+ first = true
154
+ @partition_key.each do |column|
155
+ if first
156
+ first = false
157
+ else
158
+ cql << ', '
159
+ end
160
+ cql << Util.escape_name(column.name)
161
+ end
162
+ cql << ')'
163
+ end
164
+ @clustering_columns.each do |column|
165
+ cql << ", #{Util.escape_name(column.name)}"
166
+ end
167
+ cql << ')'
168
+ end
169
+
170
+ cql << "\n)\nWITH "
171
+
172
+ if !@clustering_order.empty? && !@clustering_columns.empty?
173
+ cql << 'CLUSTERING ORDER BY ('
174
+ first = true
175
+ @clustering_columns.zip(@clustering_order) do |column, order|
176
+ if first
177
+ first = false
178
+ else
179
+ cql << ', '
180
+ end
181
+ cql << "#{Util.escape_name(column.name)} #{order.to_s.upcase}"
182
+ end
183
+ cql << ")\n AND "
184
+ end
185
+
186
+ cql << @options.to_cql.split("\n").join("\n ")
187
+
188
+ cql << ';'
189
+ end
190
+
191
+ # @private
192
+ def add_index(index)
193
+ @indexes << index
194
+ @indexes_hash[index.name] = index
195
+ end
196
+
197
+ # @private
198
+ def add_view(view)
199
+ @materialized_views << view
200
+ @materialized_views_hash[view.name] = view
201
+ end
202
+
203
+ # @private
204
+ def add_trigger(trigger)
205
+ @triggers << trigger
206
+ @triggers_hash[trigger.name] = trigger
207
+ end
208
+
209
+ # @private
210
+ def eql?(other)
211
+ other.is_a?(Table) &&
212
+ super.eql?(other) &&
213
+ @clustering_order == other.clustering_order &&
214
+ @indexes == other.indexes
215
+ end
216
+ alias == eql?
217
+
218
+ private
219
+
220
+ # @private
221
+ def type_to_cql(type, is_frozen)
222
+ case type.kind
223
+ when :tuple
224
+ "frozen <#{type}>"
225
+ when :udt
226
+ if @keyspace.name == type.keyspace
227
+ "frozen <#{Util.escape_name(type.name)}>"
228
+ else
229
+ "frozen <#{Util.escape_name(type.keyspace)}.#{Util.escape_name(type.name)}>"
230
+ end
231
+ else
232
+ if is_frozen
233
+ "frozen <#{type}>"
234
+ else
235
+ type.to_s
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 time type.
21
+ class Time
22
+ # @private
23
+ NANOSECONDS_IN_MILISECOND = 1_000_000
24
+ # @private
25
+ NANOSECONDS_IN_SECOND = NANOSECONDS_IN_MILISECOND * 1000
26
+ # @private
27
+ NANOSECONDS_IN_MINUTE = NANOSECONDS_IN_SECOND * 60
28
+ # @private
29
+ NANOSECONDS_IN_HOUR = NANOSECONDS_IN_MINUTE * 60
30
+ # @private
31
+ NANOSECONDS_IN_DAY = NANOSECONDS_IN_HOUR * 24
32
+
33
+ include ::Comparable
34
+
35
+ # @private
36
+ def initialize(nanoseconds = 0)
37
+ if nanoseconds < 0 && nanoseconds > NANOSECONDS_IN_DAY - 1
38
+ raise ::ArgumentError, 'value must be between 0 and ' \
39
+ "#{NANOSECONDS_IN_DAY}, #{value.inspect} given"
40
+ end
41
+
42
+ @nanoseconds = nanoseconds
43
+ end
44
+
45
+ # @return [Integer] an integer between 0 and 24, the number of full hours
46
+ # since midnight that this time represents
47
+ def hours
48
+ @nanoseconds / NANOSECONDS_IN_HOUR
49
+ end
50
+
51
+ # @return [Integer] an integer between 0 and 60, the number of full minutes
52
+ # since the last full hour that this time represents
53
+ def minutes
54
+ (@nanoseconds - (hours * NANOSECONDS_IN_HOUR)) / NANOSECONDS_IN_MINUTE
55
+ end
56
+
57
+ # @return [Integer] an integer between 0 and 60, the number of full seconds
58
+ # since the last full minutes that this time represents
59
+ def seconds
60
+ (@nanoseconds -
61
+ (hours * NANOSECONDS_IN_HOUR) -
62
+ (minutes * NANOSECONDS_IN_MINUTE)) / NANOSECONDS_IN_SECOND
63
+ end
64
+
65
+ # @return [Integer] an integer between 0 and 60, the number of full
66
+ # miliseconds since the last full second that this time represents
67
+ def miliseconds
68
+ (@nanoseconds -
69
+ (hours * NANOSECONDS_IN_HOUR) -
70
+ (minutes * NANOSECONDS_IN_MINUTE) -
71
+ (seconds * NANOSECONDS_IN_SECOND)) / NANOSECONDS_IN_MILISECOND
72
+ end
73
+
74
+ # @return [String] a "%H:%M%S.%3N" formatted time string
75
+ def to_s
76
+ format('%.2d:%.2d:%.2d.%.3d', hours, minutes, seconds, miliseconds)
77
+ end
78
+
79
+ # @return [Integer] an integer between 0 and 86400000000000, the number of
80
+ # nanoseconds since midnight that this time represents
81
+ def to_nanoseconds
82
+ @nanoseconds
83
+ end
84
+
85
+ # @private
86
+ def eql?(other)
87
+ other.is_a?(Time) && other.to_nanoseconds == @nanoseconds
88
+ end
89
+ alias == eql?
90
+
91
+ # @private
92
+ def <=>(other)
93
+ other <=> nanoseconds
94
+ end
95
+
96
+ # @private
97
+ def hash
98
+ # Modeled after http://developer.android.com/reference/java/lang/Object.html#writing_hashCode, but
99
+ # simplified since only one field participates in the hash.
100
+ @hash ||= 31 * 17 + @nanoseconds.hash
101
+ end
102
+ end
103
+ end