cassandra-driver 3.0.0.beta.1-java → 3.0.0-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 (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.
@@ -40,9 +40,7 @@ module Cassandra
40
40
  private
41
41
 
42
42
  def lookup_type(node, types)
43
- if node.name == 'frozen'
44
- return lookup_type(node.children.first, types)
45
- end
43
+ return lookup_type(node.children.first, types) if node.name == 'frozen'
46
44
 
47
45
  case node.name
48
46
  when 'text' then Cassandra::Types.text
@@ -64,13 +62,20 @@ module Cassandra
64
62
  when 'smallint' then Cassandra::Types.smallint
65
63
  when 'time' then Cassandra::Types.time
66
64
  when 'tinyint' then Cassandra::Types.tinyint
67
- when 'map' then Cassandra::Types.map(*node.children.map { |t| lookup_type(t, types)})
68
- when 'set' then Cassandra::Types.set(lookup_type(node.children.first, types))
69
- when 'list' then Cassandra::Types.list(lookup_type(node.children.first, types))
70
- when 'tuple' then Cassandra::Types.tuple(*node.children.map { |t| lookup_type(t, types)})
71
- when 'empty' then Cassandra::Types.custom('org.apache.cassandra.db.marshal.EmptyType')
65
+ when 'map' then
66
+ Cassandra::Types.map(*node.children.map { |t| lookup_type(t, types)})
67
+ when 'set' then
68
+ Cassandra::Types.set(lookup_type(node.children.first, types))
69
+ when 'list' then
70
+ Cassandra::Types.list(lookup_type(node.children.first, types))
71
+ when 'tuple' then
72
+ Cassandra::Types.tuple(*node.children.map { |t| lookup_type(t, types)})
73
+ when 'empty' then
74
+ Cassandra::Types.custom('org.apache.cassandra.db.marshal.EmptyType')
72
75
  else
73
- types.fetch(node.name) { raise IncompleteTypeError, "unable to lookup type #{node.name.inspect}" }
76
+ types.fetch(node.name) do
77
+ raise IncompleteTypeError, "unable to lookup type #{node.name.inspect}"
78
+ end
74
79
  end
75
80
  end
76
81
 
@@ -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.
@@ -26,20 +26,23 @@ module Cassandra
26
26
  COMPRESSION_PACKAGE_PREFIX = 'org.apache.cassandra.io.compress.'.freeze
27
27
 
28
28
  def fetch(connection)
29
+ # rubocop:disable Metrics/LineLength
29
30
  Ione::Future.all(select_keyspaces(connection),
30
31
  select_tables(connection),
31
32
  select_columns(connection),
32
33
  select_types(connection),
33
34
  select_functions(connection),
34
- select_aggregates(connection))
35
- .map do |(rows_keyspaces, rows_tables, rows_columns,
36
- rows_types, rows_functions, rows_aggregates)|
37
-
35
+ select_aggregates(connection),
36
+ select_materialized_views(connection),
37
+ select_indexes(connection))
38
+ .map do |rows_keyspaces, rows_tables, rows_columns, rows_types, rows_functions, rows_aggregates, rows_views, rows_indexes|
38
39
  lookup_tables = map_rows_by(rows_tables, 'keyspace_name')
39
40
  lookup_columns = map_rows_by(rows_columns, 'keyspace_name')
40
41
  lookup_types = map_rows_by(rows_types, 'keyspace_name')
41
42
  lookup_functions = map_rows_by(rows_functions, 'keyspace_name')
42
43
  lookup_aggregates = map_rows_by(rows_aggregates, 'keyspace_name')
44
+ lookup_views = map_rows_by(rows_views, 'keyspace_name')
45
+ lookup_indexes = map_rows_by(rows_indexes, 'keyspace_name')
43
46
 
44
47
  rows_keyspaces.map do |keyspace_data|
45
48
  name = keyspace_data['keyspace_name']
@@ -49,7 +52,9 @@ module Cassandra
49
52
  lookup_columns[name],
50
53
  lookup_types[name],
51
54
  lookup_functions[name],
52
- lookup_aggregates[name])
55
+ lookup_aggregates[name],
56
+ lookup_views[name],
57
+ lookup_indexes[name])
53
58
  end
54
59
  end
55
60
  end
@@ -60,9 +65,10 @@ module Cassandra
60
65
  select_keyspace_columns(connection, keyspace_name),
61
66
  select_keyspace_types(connection, keyspace_name),
62
67
  select_keyspace_functions(connection, keyspace_name),
63
- select_keyspace_aggregates(connection, keyspace_name))
64
- .map do |(rows_keyspaces, rows_tables, rows_columns,
65
- rows_types, rows_functions, rows_aggregates)|
68
+ select_keyspace_aggregates(connection, keyspace_name),
69
+ select_keyspace_materialized_views(connection, keyspace_name),
70
+ select_keyspace_indexes(connection, keyspace_name))
71
+ .map do |rows_keyspaces, rows_tables, rows_columns, rows_types, rows_functions, rows_aggregates, rows_views, rows_indexes|
66
72
  if rows_keyspaces.empty?
67
73
  nil
68
74
  else
@@ -71,20 +77,40 @@ module Cassandra
71
77
  rows_columns,
72
78
  rows_types,
73
79
  rows_functions,
74
- rows_aggregates)
80
+ rows_aggregates,
81
+ rows_views,
82
+ rows_indexes)
75
83
  end
76
84
  end
77
85
  end
78
86
 
79
87
  def fetch_table(connection, keyspace_name, table_name)
80
88
  Ione::Future.all(select_table(connection, keyspace_name, table_name),
81
- select_table_columns(connection, keyspace_name, table_name))
82
- .map do |(rows_tables, rows_columns)|
89
+ select_table_columns(connection, keyspace_name, table_name),
90
+ select_table_indexes(connection, keyspace_name, table_name))
91
+ .map do |(rows_tables, rows_columns, rows_indexes)|
83
92
  if rows_tables.empty?
84
93
  nil
85
94
  else
86
95
  create_table(rows_tables.first,
87
- rows_columns)
96
+ rows_columns,
97
+ rows_indexes)
98
+ end
99
+ end
100
+ end
101
+
102
+ def fetch_materialized_view(connection, keyspace_name, view_name)
103
+ Ione::Future.all(select_materialized_view(connection, keyspace_name, view_name),
104
+ select_table_columns(connection, keyspace_name, view_name))
105
+ .map do |rows_views, rows_columns|
106
+ if rows_views.empty?
107
+ nil
108
+ else
109
+ view_row = rows_views.first
110
+ base_table = @schema.keyspace(keyspace_name).table(view_row['base_table_name'])
111
+ create_materialized_view(view_row,
112
+ rows_columns,
113
+ base_table)
88
114
  end
89
115
  end
90
116
  end
@@ -100,7 +126,8 @@ module Cassandra
100
126
  end
101
127
 
102
128
  def fetch_function(connection, keyspace_name, function_name, function_args)
103
- select_function(connection, keyspace_name, function_name, function_args).map do |rows_functions|
129
+ select_function(connection, keyspace_name, function_name, function_args)
130
+ .map do |rows_functions|
104
131
  if rows_functions.empty?
105
132
  nil
106
133
  else
@@ -110,11 +137,13 @@ module Cassandra
110
137
  end
111
138
 
112
139
  def fetch_aggregate(connection, keyspace_name, aggregate_name, aggregate_args)
113
- select_aggregate(connection, keyspace_name, aggregate_name, aggregate_args).map do |rows_aggregates|
140
+ select_aggregate(connection, keyspace_name, aggregate_name, aggregate_args)
141
+ .map do |rows_aggregates|
114
142
  if rows_aggregates.empty?
115
143
  nil
116
144
  else
117
- create_aggregate(rows_aggregates.first, @schema.keyspace(keyspace_name).send(:raw_functions))
145
+ create_aggregate(rows_aggregates.first, @schema.keyspace(keyspace_name)
146
+ .send(:raw_functions))
118
147
  end
119
148
  end
120
149
  end
@@ -129,10 +158,18 @@ module Cassandra
129
158
  FUTURE_EMPTY_LIST
130
159
  end
131
160
 
161
+ def select_materialized_views(connection)
162
+ FUTURE_EMPTY_LIST
163
+ end
164
+
132
165
  def select_columns(connection)
133
166
  FUTURE_EMPTY_LIST
134
167
  end
135
168
 
169
+ def select_indexes(connection)
170
+ FUTURE_EMPTY_LIST
171
+ end
172
+
136
173
  def select_types(connection)
137
174
  FUTURE_EMPTY_LIST
138
175
  end
@@ -153,10 +190,18 @@ module Cassandra
153
190
  FUTURE_EMPTY_LIST
154
191
  end
155
192
 
193
+ def select_keyspace_materialized_views(connection, keyspace_name)
194
+ FUTURE_EMPTY_LIST
195
+ end
196
+
156
197
  def select_keyspace_columns(connection, keyspace_name)
157
198
  FUTURE_EMPTY_LIST
158
199
  end
159
200
 
201
+ def select_keyspace_indexes(connection, keyspace_name)
202
+ FUTURE_EMPTY_LIST
203
+ end
204
+
160
205
  def select_keyspace_types(connection, keyspace_name)
161
206
  FUTURE_EMPTY_LIST
162
207
  end
@@ -173,10 +218,18 @@ module Cassandra
173
218
  FUTURE_EMPTY_LIST
174
219
  end
175
220
 
221
+ def select_materialized_view(connection, keyspace_name, view_name)
222
+ FUTURE_EMPTY_LIST
223
+ end
224
+
176
225
  def select_table_columns(connection, keyspace_name, table_name)
177
226
  FUTURE_EMPTY_LIST
178
227
  end
179
228
 
229
+ def select_table_indexes(connection, keyspace_name, table_name)
230
+ FUTURE_EMPTY_LIST
231
+ end
232
+
180
233
  def select_type(connection, keyspace_name, type_name)
181
234
  FUTURE_EMPTY_LIST
182
235
  end
@@ -191,7 +244,8 @@ module Cassandra
191
244
 
192
245
  def send_select_request(connection, cql, params = EMPTY_LIST, types = EMPTY_LIST)
193
246
  backtrace = caller
194
- connection.send_request(Protocol::QueryRequest.new(cql, params, types, :one)).map do |r|
247
+ connection.send_request(
248
+ Protocol::QueryRequest.new(cql, params, types, :one)).map do |r|
195
249
  case r
196
250
  when Protocol::RowsResultResponse
197
251
  r.rows
@@ -208,30 +262,44 @@ module Cassandra
208
262
  def map_rows_by(rows, key_name, &block)
209
263
  rows.each_with_object(::Hash.new { EMPTY_LIST }) do |row, map|
210
264
  key = row[key_name]
211
- map[key] = [] unless map.has_key?(key)
265
+ map[key] = [] unless map.key?(key)
212
266
 
213
- if block
214
- map[key] << yield(row)
215
- else
216
- map[key] << row
217
- end
267
+ map[key] << if block
268
+ yield(row)
269
+ else
270
+ row
271
+ end
218
272
  end
219
273
  end
220
274
  end
221
275
 
222
276
  # @private
223
277
  module Fetchers
278
+ # rubocop:disable Style/ClassAndModuleCamelCase
224
279
  class V1_2_x
225
280
  SELECT_KEYSPACES = 'SELECT * FROM system.schema_keyspaces'.freeze
226
281
  SELECT_TABLES = 'SELECT * FROM system.schema_columnfamilies'.freeze
227
282
  SELECT_COLUMNS = 'SELECT * FROM system.schema_columns'.freeze
228
- SELECT_KEYSPACE = 'SELECT * FROM system.schema_keyspaces WHERE keyspace_name = \'%s\''.freeze
229
- SELECT_KEYSPACE_TABLES = 'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = \'%s\''.freeze
230
- SELECT_KEYSPACE_COLUMNS = 'SELECT * FROM system.schema_columns WHERE keyspace_name = \'%s\''.freeze
231
- SELECT_TABLE = 'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = \'%s\' AND columnfamily_name = \'%s\''.freeze
232
- SELECT_TABLE_COLUMNS = 'SELECT * FROM system.schema_columns WHERE keyspace_name = \'%s\' AND columnfamily_name = \'%s\''.freeze
233
-
234
- include Fetcher
283
+ SELECT_KEYSPACE =
284
+ 'SELECT * ' \
285
+ 'FROM system.schema_keyspaces ' \
286
+ 'WHERE keyspace_name = \'%s\''.freeze
287
+ SELECT_KEYSPACE_TABLES =
288
+ 'SELECT * ' \
289
+ 'FROM system.schema_columnfamilies ' \
290
+ 'WHERE keyspace_name = \'%s\''.freeze
291
+ SELECT_KEYSPACE_COLUMNS =
292
+ 'SELECT * FROM system.schema_columns WHERE keyspace_name = \'%s\''.freeze
293
+ SELECT_TABLE =
294
+ 'SELECT * ' \
295
+ 'FROM system.schema_columnfamilies ' \
296
+ 'WHERE keyspace_name = \'%s\' AND columnfamily_name = \'%s\''.freeze
297
+ SELECT_TABLE_COLUMNS =
298
+ 'SELECT * ' \
299
+ 'FROM system.schema_columns ' \
300
+ 'WHERE keyspace_name = \'%s\' AND columnfamily_name = \'%s\''.freeze
301
+
302
+ include Cassandra::Cluster::Schema::Fetcher
235
303
 
236
304
  def initialize(type_parser, schema)
237
305
  @type_parser = type_parser
@@ -257,19 +325,20 @@ module Cassandra
257
325
  end
258
326
 
259
327
  def select_keyspace_tables(connection, keyspace_name)
260
- send_select_request(connection, SELECT_KEYSPACE_TABLES % keyspace_name)
328
+ send_select_request(connection, format(SELECT_KEYSPACE_TABLES, keyspace_name))
261
329
  end
262
330
 
263
331
  def select_keyspace_columns(connection, keyspace_name)
264
- send_select_request(connection, SELECT_KEYSPACE_COLUMNS % keyspace_name)
332
+ send_select_request(connection, format(SELECT_KEYSPACE_COLUMNS, keyspace_name))
265
333
  end
266
334
 
267
335
  def select_table(connection, keyspace_name, table_name)
268
- send_select_request(connection, SELECT_TABLE % [keyspace_name, table_name])
336
+ send_select_request(connection, format(SELECT_TABLE, keyspace_name, table_name))
269
337
  end
270
338
 
271
339
  def select_table_columns(connection, keyspace_name, table_name)
272
- send_select_request(connection, SELECT_TABLE_COLUMNS % [keyspace_name, table_name])
340
+ send_select_request(connection,
341
+ format(SELECT_TABLE_COLUMNS, keyspace_name, table_name))
273
342
  end
274
343
 
275
344
  def create_replication(keyspace_data)
@@ -280,50 +349,66 @@ module Cassandra
280
349
  end
281
350
 
282
351
  def create_keyspace(keyspace_data, rows_tables, rows_columns,
283
- rows_types, rows_functions, rows_aggregates)
352
+ rows_types, rows_functions, rows_aggregates,
353
+ rows_views, rows_indexes)
284
354
  keyspace_name = keyspace_data['keyspace_name']
285
355
  replication = create_replication(keyspace_data)
286
- types = rows_types.each_with_object({}) do |row, types|
287
- types[row['type_name']] = create_type(row)
288
- end
289
-
290
- # We want the functions hash to be keyed on [name, arg-types-list].
291
- # Similarly for the aggregates hash.
356
+ types = rows_types.each_with_object({}) do |row, h|
357
+ h[row['type_name']] = create_type(row)
358
+ end
292
359
 
293
- functions = rows_functions.each_with_object({}) do |row, collector|
294
- func = create_function(row)
295
- collector[[func.name, func.argument_types]] = func
360
+ # Create a FunctionCollection for the functions and aggregates.
361
+ functions = Cassandra::FunctionCollection.new
362
+ rows_functions.each do |row|
363
+ functions.add_or_update(create_function(row))
296
364
  end
297
365
 
298
- aggregates = rows_aggregates.each_with_object({}) do |row, collector|
299
- agg = create_aggregate(row, functions)
300
- collector[[agg.name, agg.argument_types]] = agg
301
- end
366
+ aggregates = Cassandra::FunctionCollection.new
367
+ rows_aggregates.each do |row|
368
+ aggregates.add_or_update(create_aggregate(row, functions))
369
+ end
302
370
 
303
371
  lookup_columns = map_rows_by(rows_columns, 'columnfamily_name')
304
- tables = rows_tables.each_with_object({}) do |row, tables|
372
+ tables = rows_tables.each_with_object({}) do |row, h|
305
373
  table_name = row['columnfamily_name']
306
- tables[table_name] = create_table(row, lookup_columns[table_name])
374
+ # rows_indexes is nil for C* < 3.0.
375
+ h[table_name] = create_table(row, lookup_columns[table_name], nil)
307
376
  end
308
377
 
309
- Keyspace.new(keyspace_name, keyspace_data['durable_writes'],
310
- replication, tables, types, functions, aggregates)
378
+ Keyspace.new(keyspace_name,
379
+ keyspace_data['durable_writes'],
380
+ replication,
381
+ tables,
382
+ types,
383
+ functions,
384
+ aggregates,
385
+ {})
311
386
  end
312
387
 
313
- def create_table(table_data, rows_columns)
388
+ def create_table(table_data, rows_columns, rows_indexes)
314
389
  keyspace_name = table_data['keyspace_name']
315
390
  table_name = table_data['columnfamily_name']
316
391
  key_validator = @type_parser.parse(table_data['key_validator'])
317
392
  comparator = @type_parser.parse(table_data['comparator'])
318
393
  column_aliases = ::JSON.load(table_data['column_aliases'])
319
394
 
320
- if !comparator.collections.nil?
395
+ if comparator.collections.nil?
396
+ is_compact = true
397
+ if !column_aliases.empty? || rows_columns.empty?
398
+ has_value = true
399
+ clustering_size = comparator.results.size
400
+ else
401
+ has_value = false
402
+ clustering_size = 0
403
+ end
404
+ else
321
405
  size = comparator.results.size
322
406
  if !comparator.collections.empty?
323
407
  is_compact = false
324
408
  has_value = false
325
409
  clustering_size = size - 2
326
- elsif column_aliases.size == size - 1 && comparator.results.last.first == Cassandra::Types.varchar
410
+ elsif column_aliases.size == size - 1 &&
411
+ comparator.results.last.first == Cassandra::Types.varchar
327
412
  is_compact = false
328
413
  has_value = false
329
414
  clustering_size = size - 1
@@ -332,39 +417,32 @@ module Cassandra
332
417
  has_value = (!column_aliases.empty? || rows_columns.empty?)
333
418
  clustering_size = size
334
419
  end
335
- else
336
- is_compact = true
337
- if (!column_aliases.empty? || rows_columns.empty?)
338
- has_value = true
339
- clustering_size = comparator.results.size
340
- else
341
- has_value = false
342
- clustering_size = 0
343
- end
344
420
  end
345
421
 
422
+ # Separate out the partition-key, clustering-columns, and other-columns
346
423
  partition_key = []
347
424
  clustering_columns = []
348
425
  clustering_order = []
426
+ other_columns = []
349
427
 
350
428
  compaction_strategy = create_compaction_strategy(table_data)
351
- table_options = create_table_options(table_data, compaction_strategy, is_compact)
352
- table_columns = {}
353
- other_columns = []
429
+ table_options =
430
+ create_table_options(table_data, compaction_strategy, is_compact)
354
431
 
355
432
  key_aliases = ::JSON.load(table_data['key_aliases'])
356
433
 
357
434
  key_validator.results.each_with_index do |(type, order, is_frozen), i|
358
- key_alias = key_aliases.fetch(i) { i.zero? ? "key" : "key#{i + 1}" }
435
+ key_alias = key_aliases.fetch(i) { i.zero? ? 'key' : "key#{i + 1}" }
359
436
 
360
- partition_key[i] = Column.new(key_alias, type, order, nil, false, is_frozen)
437
+ partition_key[i] = Column.new(key_alias, type, order, false, is_frozen)
361
438
  end
362
439
 
363
440
  clustering_size.times do |i|
364
441
  column_alias = column_aliases.fetch(i) { "column#{i + 1}" }
365
442
  type, order, is_frozen = comparator.results.fetch(i)
366
443
 
367
- clustering_columns[i] = Column.new(column_alias, type, order, nil, false, is_frozen)
444
+ clustering_columns[i] =
445
+ Column.new(column_alias, type, order, false, is_frozen)
368
446
  clustering_order[i] = order
369
447
  end
370
448
 
@@ -373,59 +451,87 @@ module Cassandra
373
451
  value_alias ||= 'value'
374
452
 
375
453
  unless value_alias.empty?
376
- type, order, is_frozen = @type_parser.parse(table_data['default_validator']).results.first
377
- other_columns << Column.new(value_alias, type, order, nil, false, is_frozen)
454
+ type, order, is_frozen =
455
+ @type_parser.parse(table_data['default_validator']).results.first
456
+ other_columns <<
457
+ Column.new(value_alias, type, order, false, is_frozen)
378
458
  end
379
459
  end
380
460
 
461
+ index_rows = []
381
462
  rows_columns.each do |row|
382
- other_columns << create_column(row)
383
- end
463
+ column = create_column(row)
464
+ other_columns << column
384
465
 
385
- partition_key.each do |column|
386
- table_columns[column.name] = column
466
+ # In C* 1.2.x, index info is in the column metadata; rows_indexes is nil.
467
+ index_rows << [column, row] unless row['index_type'].nil?
387
468
  end
388
469
 
389
- clustering_columns.each do |column|
390
- table_columns[column.name] = column
470
+ table = Cassandra::Table.new(@schema.keyspace(keyspace_name),
471
+ table_name,
472
+ partition_key,
473
+ clustering_columns,
474
+ other_columns,
475
+ table_options,
476
+ clustering_order,
477
+ table_data['id'])
478
+
479
+ # Create Index objects and add them to the table.
480
+ index_rows.each do |column, row|
481
+ create_index(table, column, row)
391
482
  end
483
+ table
484
+ end
392
485
 
393
- other_columns.each do |column|
394
- table_columns[column.name] = column
486
+ def create_index(table, column, row_column)
487
+ # Most of this logic was taken from the Java driver.
488
+ options = {}
489
+ # For some versions of C*, this field could have a literal string 'null' value.
490
+ if !row_column['index_options'].nil? && row_column['index_options'] != 'null' && !row_column['index_options'].empty?
491
+ options = ::JSON.load(row_column['index_options'])
395
492
  end
396
-
397
- Table.new(keyspace_name, table_name, partition_key, clustering_columns,
398
- table_columns, table_options, clustering_order)
493
+ column_name = Util.escape_name(column.name)
494
+ target = if options.key?('index_keys')
495
+ "keys(#{column_name})"
496
+ elsif options.key?('index_keys_and_values')
497
+ "entries(#{column_name})"
498
+ elsif column.frozen? && (column.type == Cassandra::Types::Set ||
499
+ column.type == Cassandra::Types::List ||
500
+ column.type == Cassandra::Types::Map)
501
+ "full(#{column_name})"
502
+ else
503
+ column_name
504
+ end
505
+
506
+ table.add_index(Cassandra::Index.new(table,
507
+ row_column['index_name'],
508
+ row_column['index_type'].downcase.to_sym,
509
+ target,
510
+ options))
399
511
  end
400
512
 
401
513
  def create_column(column_data)
402
514
  name = column_data['column_name']
403
515
  is_static = (column_data['type'] == 'STATIC')
404
- type, order, is_frozen = @type_parser.parse(column_data['validator']).results.first
405
-
406
- if column_data['index_type'].nil?
407
- index = nil
408
- elsif column_data['index_type'].to_s.upcase == 'CUSTOM' || !column_data['index_options']
409
- index = Column::Index.new(column_data['index_name'])
410
- else
411
- options = ::JSON.load(column_data['index_options'])
412
- index = Column::Index.new(column_data['index_name'], options && options['class_name'])
413
- end
414
-
415
- Column.new(name, type, order, index, is_static, is_frozen)
516
+ type, order, is_frozen =
517
+ @type_parser.parse(column_data['validator']).results.first
518
+ Column.new(name, type, order, is_static, is_frozen)
416
519
  end
417
520
 
418
521
  def create_compaction_strategy(table_data)
419
522
  klass = table_data['compaction_strategy_class']
420
523
  klass.slice!('org.apache.cassandra.db.compaction.')
421
524
  options = ::JSON.load(table_data['compaction_strategy_options'])
422
- Table::Compaction.new(klass, options)
525
+ ColumnContainer::Compaction.new(klass, options)
423
526
  end
424
527
 
425
528
  def create_table_options(table_data, compaction_strategy, is_compact)
426
529
  compression_parameters = ::JSON.load(table_data['compression_parameters'])
427
- compression_parameters['sstable_compression'].slice!(COMPRESSION_PACKAGE_PREFIX) if compression_parameters['sstable_compression']
428
- Table::Options.new(
530
+ if compression_parameters['sstable_compression']
531
+ compression_parameters['sstable_compression']
532
+ .slice!(COMPRESSION_PACKAGE_PREFIX)
533
+ end
534
+ Cassandra::ColumnContainer::Options.new(
429
535
  table_data['comment'],
430
536
  table_data['read_repair_chance'],
431
537
  table_data['local_read_repair_chance'],
@@ -442,72 +548,87 @@ module Cassandra
442
548
  nil,
443
549
  compaction_strategy,
444
550
  compression_parameters,
445
- is_compact
551
+ is_compact,
552
+ table_data['crc_check_chance'],
553
+ table_data['extensions']
446
554
  )
447
555
  end
448
556
  end
449
557
 
450
558
  class V2_0_x < V1_2_x
451
- SELECT_KEYSPACE = 'SELECT * FROM system.schema_keyspaces WHERE keyspace_name = ?'.freeze
452
- SELECT_KEYSPACE_TABLES = 'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = ?'.freeze
453
- SELECT_KEYSPACE_COLUMNS = 'SELECT * FROM system.schema_columns WHERE keyspace_name = ?'.freeze
454
- SELECT_TABLE = 'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
455
- SELECT_TABLE_COLUMNS = 'SELECT * FROM system.schema_columns WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
559
+ SELECT_KEYSPACE =
560
+ 'SELECT * FROM system.schema_keyspaces WHERE keyspace_name = ?'.freeze
561
+ SELECT_KEYSPACE_TABLES =
562
+ 'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = ?'.freeze
563
+ SELECT_KEYSPACE_COLUMNS =
564
+ 'SELECT * FROM system.schema_columns WHERE keyspace_name = ?'.freeze
565
+ SELECT_TABLE =
566
+ 'SELECT * ' \
567
+ 'FROM system.schema_columnfamilies ' \
568
+ 'WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
569
+ SELECT_TABLE_COLUMNS =
570
+ 'SELECT * ' \
571
+ 'FROM system.schema_columns ' \
572
+ 'WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
456
573
 
457
574
  private
458
575
 
459
- def create_table(table_data, rows_columns)
576
+ def create_table(table_data, rows_columns, rows_indexes)
460
577
  keyspace_name = table_data['keyspace_name']
461
578
  table_name = table_data['columnfamily_name']
462
579
  comparator = @type_parser.parse(table_data['comparator'])
463
- table_columns = {}
464
- other_columns = []
465
580
  clustering_size = 0
466
581
 
582
+ # Separate out partition-key, clustering columns, other columns.
467
583
  partition_key = []
468
584
  clustering_columns = []
469
585
  clustering_order = []
586
+ other_columns = []
470
587
 
588
+ index_rows = []
471
589
  rows_columns.each do |row|
472
590
  next if row['column_name'].empty?
473
591
 
474
592
  column = create_column(row)
475
593
  type = row['type'].to_s
476
- index = row['component_index'] || 0
594
+ ind = row['component_index'] || 0
477
595
 
478
596
  case type.upcase
479
597
  when 'PARTITION_KEY'
480
- partition_key[index] = column
598
+ partition_key[ind] = column
481
599
  when 'CLUSTERING_KEY'
482
- clustering_columns[index] = column
483
- clustering_order[index] = column.order
600
+ clustering_columns[ind] = column
601
+ clustering_order[ind] = column.order
484
602
 
485
- if clustering_size.zero? || index == clustering_size
486
- clustering_size = index + 1
487
- end
603
+ clustering_size = ind + 1 if clustering_size.zero? || ind == clustering_size
488
604
  else
489
605
  other_columns << column
490
606
  end
491
- end
492
-
493
- partition_key.each do |column|
494
- table_columns[column.name] = column
495
- end
496
607
 
497
- clustering_columns.each do |column|
498
- table_columns[column.name] = column
499
- end
500
-
501
- other_columns.each do |column|
502
- table_columns[column.name] = column
608
+ # In C* 2.0.x, index info is in the column metadata; rows_indexes is nil.
609
+ index_rows << [column, row] unless row['index_type'].nil?
503
610
  end
504
611
 
505
612
  compaction_strategy = create_compaction_strategy(table_data)
506
- is_compact = (clustering_size != comparator.results.size - 1) || !comparator.collections
507
- table_options = create_table_options(table_data, compaction_strategy, is_compact)
508
-
509
- Table.new(keyspace_name, table_name, partition_key, clustering_columns,
510
- table_columns, table_options, clustering_order)
613
+ is_compact = (clustering_size != comparator.results.size - 1) ||
614
+ !comparator.collections
615
+ table_options =
616
+ create_table_options(table_data, compaction_strategy, is_compact)
617
+
618
+ table = Cassandra::Table.new(@schema.keyspace(keyspace_name),
619
+ table_name,
620
+ partition_key,
621
+ clustering_columns,
622
+ other_columns,
623
+ table_options,
624
+ clustering_order,
625
+ table_data['id'])
626
+
627
+ # Create Index objects and add them to the table.
628
+ index_rows.each do |column, row|
629
+ create_index(table, column, row)
630
+ end
631
+ table
511
632
  end
512
633
 
513
634
  def select_keyspace(connection, keyspace_name)
@@ -542,8 +663,11 @@ module Cassandra
542
663
 
543
664
  def create_table_options(table_data, compaction_strategy, is_compact)
544
665
  compression_parameters = ::JSON.load(table_data['compression_parameters'])
545
- compression_parameters['sstable_compression'].slice!(COMPRESSION_PACKAGE_PREFIX) if compression_parameters['sstable_compression']
546
- Table::Options.new(
666
+ if compression_parameters['sstable_compression']
667
+ compression_parameters['sstable_compression']
668
+ .slice!(COMPRESSION_PACKAGE_PREFIX)
669
+ end
670
+ Cassandra::ColumnContainer::Options.new(
547
671
  table_data['comment'],
548
672
  table_data['read_repair_chance'],
549
673
  table_data['local_read_repair_chance'],
@@ -560,15 +684,21 @@ module Cassandra
560
684
  nil,
561
685
  compaction_strategy,
562
686
  compression_parameters,
563
- is_compact
687
+ is_compact,
688
+ table_data['crc_check_chance'],
689
+ table_data['extensions']
564
690
  )
565
691
  end
566
692
  end
567
693
 
568
694
  class V2_1_x < V2_0_x
569
695
  SELECT_TYPES = 'SELECT * FROM system.schema_usertypes'.freeze
570
- SELECT_KEYSPACE_TYPES = 'SELECT * FROM system.schema_usertypes WHERE keyspace_name = ?'.freeze
571
- SELECT_TYPE = 'SELECT * FROM system.schema_usertypes WHERE keyspace_name = ? AND type_name = ?'.freeze
696
+ SELECT_KEYSPACE_TYPES =
697
+ 'SELECT * FROM system.schema_usertypes WHERE keyspace_name = ?'.freeze
698
+ SELECT_TYPE =
699
+ 'SELECT * ' \
700
+ 'FROM system.schema_usertypes ' \
701
+ 'WHERE keyspace_name = ? AND type_name = ?'.freeze
572
702
 
573
703
  private
574
704
 
@@ -607,8 +737,11 @@ module Cassandra
607
737
 
608
738
  def create_table_options(table_data, compaction_strategy, is_compact)
609
739
  compression_parameters = ::JSON.load(table_data['compression_parameters'])
610
- compression_parameters['sstable_compression'].slice!(COMPRESSION_PACKAGE_PREFIX) if compression_parameters['sstable_compression']
611
- Table::Options.new(
740
+ if compression_parameters['sstable_compression']
741
+ compression_parameters['sstable_compression']
742
+ .slice!(COMPRESSION_PACKAGE_PREFIX)
743
+ end
744
+ Cassandra::ColumnContainer::Options.new(
612
745
  table_data['comment'],
613
746
  table_data['read_repair_chance'],
614
747
  table_data['local_read_repair_chance'],
@@ -625,7 +758,9 @@ module Cassandra
625
758
  table_data['max_index_interval'],
626
759
  compaction_strategy,
627
760
  compression_parameters,
628
- is_compact
761
+ is_compact,
762
+ table_data['crc_check_chance'],
763
+ table_data['extensions']
629
764
  )
630
765
  end
631
766
  end
@@ -633,12 +768,23 @@ module Cassandra
633
768
  class V2_2_x < V2_1_x
634
769
  SELECT_FUNCTIONS = 'SELECT * FROM system.schema_functions'.freeze
635
770
  SELECT_AGGREGATES = 'SELECT * FROM system.schema_aggregates'.freeze
636
- SELECT_KEYSPACE_FUNCTIONS = 'SELECT * FROM system.schema_functions WHERE keyspace_name = ?'.freeze
637
- SELECT_KEYSPACE_AGGREGATES = 'SELECT * FROM system.schema_aggregates WHERE keyspace_name = ?'.freeze
638
- SELECT_FUNCTION = 'SELECT * FROM system.schema_functions WHERE keyspace_name = ? AND function_name = ? AND argument_types = ?'.freeze
639
- SELECT_AGGREGATE = 'SELECT * FROM system.schema_aggregates WHERE keyspace_name = ? AND aggregate_name = ? AND argument_types = ?'.freeze
640
-
641
- # parse an array of string argument types and return an array of [Cassandra::Type]s.
771
+ SELECT_KEYSPACE_FUNCTIONS =
772
+ 'SELECT * FROM system.schema_functions WHERE keyspace_name = ?'.freeze
773
+ SELECT_KEYSPACE_AGGREGATES =
774
+ 'SELECT * FROM system.schema_aggregates WHERE keyspace_name = ?'.freeze
775
+ SELECT_FUNCTION =
776
+ 'SELECT * ' \
777
+ 'FROM system.schema_functions ' \
778
+ 'WHERE keyspace_name = ? AND function_name = ? ' \
779
+ 'AND argument_types = ?'.freeze
780
+ SELECT_AGGREGATE =
781
+ 'SELECT * ' \
782
+ 'FROM system.schema_aggregates ' \
783
+ 'WHERE keyspace_name = ? AND aggregate_name = ? ' \
784
+ 'AND argument_types = ?'.freeze
785
+
786
+ # parse an array of string argument types and return an array of
787
+ # [Cassandra::Type]s.
642
788
  # @param connection a connection to a Cassandra node.
643
789
  # @param keyspace_name [String] name of the keyspace.
644
790
  # @param argument_types [Array<String>] array of argument types.
@@ -655,35 +801,59 @@ module Cassandra
655
801
  keyspace_name = function_data['keyspace_name']
656
802
  function_name = function_data['function_name']
657
803
  function_lang = function_data['language']
658
- function_type = @type_parser.parse(function_data['return_type']).results.first.first
804
+ function_type =
805
+ @type_parser.parse(function_data['return_type']).results.first.first
659
806
  function_body = function_data['body']
660
807
  called_on_null = function_data['called_on_null_input']
661
808
 
662
809
  arguments = []
663
810
 
664
- Array(function_data['argument_names']).zip(Array(function_data['argument_types'])) do |argument_name, fqcn|
811
+ Array(function_data['argument_names'])
812
+ .zip(Array(function_data['argument_types'])) do |argument_name, fqcn|
665
813
  argument_type = @type_parser.parse(fqcn).results.first.first
666
814
  arguments << Argument.new(argument_name, argument_type)
667
815
  end
668
816
 
669
- Function.new(keyspace_name, function_name, function_lang, function_type, arguments, function_body, called_on_null)
817
+ Cassandra::Function.new(keyspace_name,
818
+ function_name,
819
+ function_lang,
820
+ function_type,
821
+ arguments,
822
+ function_body,
823
+ called_on_null)
670
824
  end
671
825
 
672
826
  def create_aggregate(aggregate_data, functions)
673
827
  keyspace_name = aggregate_data['keyspace_name']
674
828
  aggregate_name = aggregate_data['aggregate_name']
675
- aggregate_type = @type_parser.parse(aggregate_data['return_type']).results.first.first
676
- argument_types = aggregate_data['argument_types'].map {|fqcn| @type_parser.parse(fqcn).results.first.first}.freeze
677
- state_type = @type_parser.parse(aggregate_data['state_type']).results.first.first
678
- initial_state = Util.encode_object(Protocol::Coder.read_value_v4(Protocol::CqlByteBuffer.new.append_bytes(aggregate_data['initcond']), state_type))
829
+ aggregate_type =
830
+ @type_parser.parse(aggregate_data['return_type']).results.first.first
831
+ argument_types = aggregate_data['argument_types'].map do |fqcn|
832
+ @type_parser.parse(fqcn).results.first.first
833
+ end.freeze
834
+ state_type =
835
+ @type_parser.parse(aggregate_data['state_type']).results.first.first
836
+ initial_state = Util.encode_object(
837
+ Protocol::Coder.read_value_v4(
838
+ Protocol::CqlByteBuffer.new.append_bytes(aggregate_data['initcond']),
839
+ state_type))
679
840
 
680
841
  # The state-function takes arguments: first the stype, then the args of the aggregate.
681
- state_function = functions[[aggregate_data['state_func'], [state_type].concat(argument_types)]]
842
+ state_function = functions.get(aggregate_data['state_func'],
843
+ [state_type].concat(argument_types))
682
844
 
683
845
  # The final-function takes an stype argument.
684
- final_function = functions[[aggregate_data['final_func'], [state_type]]]
846
+ final_function = functions.get(aggregate_data['final_func'],
847
+ [state_type])
685
848
 
686
- Aggregate.new(keyspace_name, aggregate_name, aggregate_type, argument_types, state_type, initial_state, state_function, final_function)
849
+ Aggregate.new(keyspace_name,
850
+ aggregate_name,
851
+ aggregate_type,
852
+ argument_types,
853
+ state_type,
854
+ initial_state,
855
+ state_function,
856
+ final_function)
687
857
  end
688
858
 
689
859
  def select_functions(connection)
@@ -720,32 +890,69 @@ module Cassandra
720
890
  end
721
891
 
722
892
  class V3_0_x < V2_2_x
723
- SELECT_KEYSPACES = "SELECT * FROM system_schema.keyspaces".freeze
724
- SELECT_TABLES = "SELECT * FROM system_schema.tables".freeze
725
- SELECT_COLUMNS = "SELECT * FROM system_schema.columns".freeze
726
- SELECT_TYPES = "SELECT * FROM system_schema.types".freeze
727
- SELECT_FUNCTIONS = "SELECT * FROM system_schema.functions".freeze
728
- SELECT_AGGREGATES = "SELECT * FROM system_schema.aggregates".freeze
729
- SELECT_INDEXES = "SELECT * FROM system_schema.indexes".freeze
730
- SELECT_VIEWS = "SELECT * FROM system_schema.materialized_views".freeze
731
-
732
- SELECT_KEYSPACE = 'SELECT * FROM system_schema.keyspaces WHERE keyspace_name = ?'.freeze
733
- SELECT_KEYSPACE_TABLES = 'SELECT * FROM system_schema.tables WHERE keyspace_name = ?'.freeze
734
- SELECT_KEYSPACE_COLUMNS = 'SELECT * FROM system_schema.columns WHERE keyspace_name = ?'.freeze
735
- SELECT_KEYSPACE_TYPES = "SELECT * FROM system_schema.types WHERE keyspace_name = ?".freeze
736
- SELECT_KEYSPACE_FUNCTIONS = 'SELECT * FROM system_schema.functions WHERE keyspace_name = ?'.freeze
737
- SELECT_KEYSPACE_AGGREGATES = 'SELECT * FROM system_schema.aggregates WHERE keyspace_name = ?'.freeze
738
-
739
- SELECT_TABLE = 'SELECT * FROM system_schema.tables WHERE keyspace_name = ? AND table_name = ?'.freeze
740
- SELECT_TABLE_COLUMNS = 'SELECT * FROM system_schema.columns WHERE keyspace_name = ? AND table_name = ?'.freeze
741
-
742
- SELECT_TYPE = 'SELECT * FROM system_schema.types WHERE keyspace_name = ? AND type_name = ?'.freeze
743
-
744
- SELECT_FUNCTION = 'SELECT * FROM system_schema.functions WHERE keyspace_name = ? AND function_name = ? AND argument_types = ?'.freeze
745
-
746
- SELECT_AGGREGATE = 'SELECT * FROM system_schema.aggregates WHERE keyspace_name = ? AND aggregate_name = ? AND argument_types = ?'.freeze
747
-
748
- # parse an array of string argument types and return an array of [Cassandra::Type]s.
893
+ SELECT_KEYSPACES = 'SELECT * FROM system_schema.keyspaces'.freeze
894
+ SELECT_TABLES = 'SELECT * FROM system_schema.tables'.freeze
895
+ SELECT_COLUMNS = 'SELECT * FROM system_schema.columns'.freeze
896
+ SELECT_TYPES = 'SELECT * FROM system_schema.types'.freeze
897
+ SELECT_FUNCTIONS = 'SELECT * FROM system_schema.functions'.freeze
898
+ SELECT_AGGREGATES = 'SELECT * FROM system_schema.aggregates'.freeze
899
+ SELECT_INDEXES = 'SELECT * FROM system_schema.indexes'.freeze
900
+ SELECT_VIEWS = 'SELECT * FROM system_schema.views'.freeze
901
+
902
+ SELECT_KEYSPACE =
903
+ 'SELECT * FROM system_schema.keyspaces WHERE keyspace_name = ?'.freeze
904
+ SELECT_KEYSPACE_TABLES =
905
+ 'SELECT * FROM system_schema.tables WHERE keyspace_name = ?'.freeze
906
+ SELECT_KEYSPACE_INDEXES =
907
+ 'SELECT * FROM system_schema.indexes WHERE keyspace_name = ?'.freeze
908
+ SELECT_KEYSPACE_COLUMNS =
909
+ 'SELECT * FROM system_schema.columns WHERE keyspace_name = ?'.freeze
910
+ SELECT_KEYSPACE_VIEWS =
911
+ 'SELECT * FROM system_schema.views WHERE keyspace_name = ?'.freeze
912
+ SELECT_KEYSPACE_TYPES =
913
+ 'SELECT * FROM system_schema.types WHERE keyspace_name = ?'.freeze
914
+ SELECT_KEYSPACE_FUNCTIONS =
915
+ 'SELECT * FROM system_schema.functions WHERE keyspace_name = ?'.freeze
916
+ SELECT_KEYSPACE_AGGREGATES =
917
+ 'SELECT * FROM system_schema.aggregates WHERE keyspace_name = ?'.freeze
918
+
919
+ SELECT_TABLE =
920
+ 'SELECT * ' \
921
+ 'FROM system_schema.tables ' \
922
+ 'WHERE keyspace_name = ? AND table_name = ?'.freeze
923
+ SELECT_TABLE_COLUMNS =
924
+ 'SELECT * ' \
925
+ 'FROM system_schema.columns ' \
926
+ 'WHERE keyspace_name = ? AND table_name = ?'.freeze
927
+ SELECT_TABLE_INDEXES =
928
+ 'SELECT * ' \
929
+ 'FROM system_schema.indexes ' \
930
+ 'WHERE keyspace_name = ? AND table_name = ?'.freeze
931
+
932
+ SELECT_VIEW =
933
+ 'SELECT * ' \
934
+ 'FROM system_schema.views ' \
935
+ 'WHERE keyspace_name = ? AND view_name = ?'.freeze
936
+
937
+ SELECT_TYPE =
938
+ 'SELECT * ' \
939
+ 'FROM system_schema.types ' \
940
+ 'WHERE keyspace_name = ? AND type_name = ?'.freeze
941
+
942
+ SELECT_FUNCTION =
943
+ 'SELECT * ' \
944
+ 'FROM system_schema.functions ' \
945
+ 'WHERE keyspace_name = ? AND function_name = ? ' \
946
+ 'AND argument_types = ?'.freeze
947
+
948
+ SELECT_AGGREGATE =
949
+ 'SELECT * ' \
950
+ 'FROM system_schema.aggregates ' \
951
+ 'WHERE keyspace_name = ? AND aggregate_name = ? ' \
952
+ 'AND argument_types = ?'.freeze
953
+
954
+ # parse an array of string argument types and return an array of
955
+ # [Cassandra::Type]s.
749
956
  # @param connection a connection to a Cassandra node.
750
957
  # @param keyspace_name [String] name of the keyspace.
751
958
  # @param argument_types [Array<String>] array of argument types.
@@ -767,6 +974,14 @@ module Cassandra
767
974
  send_select_request(connection, SELECT_TABLES)
768
975
  end
769
976
 
977
+ def select_indexes(connection)
978
+ send_select_request(connection, SELECT_INDEXES)
979
+ end
980
+
981
+ def select_materialized_views(connection)
982
+ send_select_request(connection, SELECT_VIEWS)
983
+ end
984
+
770
985
  def select_columns(connection)
771
986
  send_select_request(connection, SELECT_COLUMNS)
772
987
  end
@@ -801,6 +1016,18 @@ module Cassandra
801
1016
  send_select_request(connection, SELECT_KEYSPACE_COLUMNS, params, hints)
802
1017
  end
803
1018
 
1019
+ def select_keyspace_indexes(connection, keyspace_name)
1020
+ params = [keyspace_name]
1021
+ hints = [Types.varchar]
1022
+ send_select_request(connection, SELECT_KEYSPACE_INDEXES, params, hints)
1023
+ end
1024
+
1025
+ def select_keyspace_materialized_views(connection, keyspace_name)
1026
+ params = [keyspace_name]
1027
+ hints = [Types.varchar]
1028
+ send_select_request(connection, SELECT_KEYSPACE_VIEWS, params, hints)
1029
+ end
1030
+
804
1031
  def select_keyspace_types(connection, keyspace_name)
805
1032
  params = [keyspace_name]
806
1033
  hints = [Types.varchar]
@@ -826,11 +1053,26 @@ module Cassandra
826
1053
  end
827
1054
 
828
1055
  def select_table_columns(connection, keyspace_name, table_name)
1056
+ # This is identical to the 2.0 impl, but the SELECT_TABLE_COLUMNS query
1057
+ # is different between the two, so we need two impls. :(
1058
+ # Also, this method works fine for finding view columns as well.
829
1059
  params = [keyspace_name, table_name]
830
1060
  hints = [Types.varchar, Types.varchar]
831
1061
  send_select_request(connection, SELECT_TABLE_COLUMNS, params, hints)
832
1062
  end
833
1063
 
1064
+ def select_table_indexes(connection, keyspace_name, table_name)
1065
+ params = [keyspace_name, table_name]
1066
+ hints = [Types.varchar, Types.varchar]
1067
+ send_select_request(connection, SELECT_TABLE_INDEXES, params, hints)
1068
+ end
1069
+
1070
+ def select_materialized_view(connection, keyspace_name, view_name)
1071
+ params = [keyspace_name, view_name]
1072
+ hints = [Types.varchar, Types.varchar]
1073
+ send_select_request(connection, SELECT_VIEW, params, hints)
1074
+ end
1075
+
834
1076
  def select_type(connection, keyspace_name, type_name)
835
1077
  params = [keyspace_name, type_name]
836
1078
  hints = [Types.varchar, Types.varchar]
@@ -860,29 +1102,50 @@ module Cassandra
860
1102
 
861
1103
  arguments = []
862
1104
 
863
- function_data['argument_names'].zip(function_data['argument_types']) do |argument_name, argument_type|
864
- arguments << Argument.new(argument_name, @type_parser.parse(argument_type, types).first)
1105
+ function_data['argument_names']
1106
+ .zip(function_data['argument_types']) do |argument_name, argument_type|
1107
+ arguments << Argument.new(argument_name,
1108
+ @type_parser.parse(argument_type, types).first)
865
1109
  end
866
1110
 
867
- Function.new(keyspace_name, function_name, function_lang, function_type, arguments, function_body, called_on_null)
1111
+ Cassandra::Function.new(keyspace_name,
1112
+ function_name,
1113
+ function_lang,
1114
+ function_type,
1115
+ arguments,
1116
+ function_body,
1117
+ called_on_null)
868
1118
  end
869
1119
 
870
1120
  def create_aggregate(aggregate_data, functions, types = nil)
871
1121
  keyspace_name = aggregate_data['keyspace_name']
872
1122
  aggregate_name = aggregate_data['aggregate_name']
873
1123
  types ||= @schema.keyspace(keyspace_name).send(:raw_types)
874
- aggregate_type = @type_parser.parse(aggregate_data['return_type'], types).first
875
- argument_types = aggregate_data['argument_types'].map {|argument_type| @type_parser.parse(argument_type, types).first}.freeze
1124
+ aggregate_type =
1125
+ @type_parser.parse(aggregate_data['return_type'], types).first
1126
+ argument_types = aggregate_data['argument_types'].map do |argument_type|
1127
+ @type_parser.parse(argument_type, types).first
1128
+ end.freeze
876
1129
  state_type = @type_parser.parse(aggregate_data['state_type'], types).first
877
1130
  initial_state = aggregate_data['initcond'] || 'null'
878
1131
 
879
- # The state-function takes arguments: first the stype, then the args of the aggregate.
880
- state_function = functions[[aggregate_data['state_func'], [state_type].concat(argument_types)]]
1132
+ # The state-function takes arguments: first the stype, then the args of the
1133
+ # aggregate.
1134
+ state_function = functions.get(aggregate_data['state_func'],
1135
+ [state_type].concat(argument_types))
881
1136
 
882
1137
  # The final-function takes an stype argument.
883
- final_function = functions[[aggregate_data['final_func'], [state_type]]]
1138
+ final_function = functions.get(aggregate_data['final_func'],
1139
+ [state_type])
884
1140
 
885
- Aggregate.new(keyspace_name, aggregate_name, aggregate_type, argument_types, state_type, initial_state, state_function, final_function)
1141
+ Aggregate.new(keyspace_name,
1142
+ aggregate_name,
1143
+ aggregate_type,
1144
+ argument_types,
1145
+ state_type,
1146
+ initial_state,
1147
+ state_function,
1148
+ final_function)
886
1149
  end
887
1150
 
888
1151
  def create_types(rows_types, types)
@@ -914,43 +1177,60 @@ module Cassandra
914
1177
 
915
1178
  break if skipped_rows.empty?
916
1179
 
917
- if rows_size == skipped_rows.size
918
- raise "Unable to resolve circular references among UDTs when parsing"
919
- else
920
- rows_types, skipped_rows = skipped_rows, rows_types
921
- end
1180
+ raise 'Unable to resolve circular references among UDTs when parsing' if rows_size == skipped_rows.size
1181
+
1182
+ rows_types, skipped_rows = skipped_rows, rows_types
922
1183
  end
923
1184
  end
924
1185
 
925
- def create_keyspace(keyspace_data, rows_tables, rows_columns,
926
- rows_types, rows_functions, rows_aggregates)
1186
+ def create_keyspace(keyspace_data, rows_tables, rows_columns, rows_types,
1187
+ rows_functions, rows_aggregates, rows_views, rows_indexes)
927
1188
  keyspace_name = keyspace_data['keyspace_name']
928
1189
  replication = create_replication(keyspace_data)
929
1190
 
930
1191
  types = ::Hash.new
931
1192
  create_types(rows_types, types)
932
1193
 
933
- # We want the functions hash to be keyed on [name, arg-types-list].
934
- # Similarly for the aggregates hash.
935
-
936
- functions = rows_functions.each_with_object({}) do |row, collector|
937
- func = create_function(row, types)
938
- collector[[func.name, func.argument_types]] = func
1194
+ # Create a FunctionCollection for the functions and aggregates.
1195
+ functions = Cassandra::FunctionCollection.new
1196
+ rows_functions.each do |row|
1197
+ functions.add_or_update(create_function(row, types))
939
1198
  end
940
1199
 
941
- aggregates = rows_aggregates.each_with_object({}) do |row, collector|
942
- agg = create_aggregate(row, functions, types)
943
- collector[[agg.name, agg.argument_types]] = agg
1200
+ aggregates = Cassandra::FunctionCollection.new
1201
+ rows_aggregates.each do |row|
1202
+ aggregates.add_or_update(create_aggregate(row, functions, types))
944
1203
  end
945
1204
 
1205
+ # lookup_columns is a hash of <table-name, rows_columns for that table>.
1206
+ # However, views are analogous to tables in this context, so we get
1207
+ # view columns organized by view-name also.
1208
+
946
1209
  lookup_columns = map_rows_by(rows_columns, 'table_name')
947
- tables = rows_tables.each_with_object({}) do |row, tables|
1210
+ lookup_indexes = map_rows_by(rows_indexes, 'table_name')
1211
+ tables = rows_tables.each_with_object({}) do |row, h|
948
1212
  table_name = row['table_name']
949
- tables[table_name] = create_table(row, lookup_columns[table_name], types)
1213
+ h[table_name] = create_table(row, lookup_columns[table_name],
1214
+ lookup_indexes[table_name], types)
950
1215
  end
951
1216
 
952
- Keyspace.new(keyspace_name, keyspace_data['durable_writes'],
953
- replication, tables, types, functions, aggregates)
1217
+ views = rows_views.each_with_object({}) do |row, h|
1218
+ view_name = row['view_name']
1219
+ base_table = tables[row['base_table_name']]
1220
+ h[view_name] = create_materialized_view(row,
1221
+ lookup_columns[view_name],
1222
+ base_table,
1223
+ types)
1224
+ end
1225
+
1226
+ Keyspace.new(keyspace_name,
1227
+ keyspace_data['durable_writes'],
1228
+ replication,
1229
+ tables,
1230
+ types,
1231
+ functions,
1232
+ aggregates,
1233
+ views)
954
1234
  end
955
1235
 
956
1236
  def create_replication(keyspace_data)
@@ -964,14 +1244,14 @@ module Cassandra
964
1244
  options = table_data['compaction']
965
1245
  klass = options.delete('class')
966
1246
  klass.slice!('org.apache.cassandra.db.compaction.')
967
- Table::Compaction.new(klass, options)
1247
+ ColumnContainer::Compaction.new(klass, options)
968
1248
  end
969
1249
 
970
1250
  def create_table_options(table_data, compaction_strategy, is_compact)
971
1251
  compression = table_data['compression']
972
1252
  compression['class'].slice!(COMPRESSION_PACKAGE_PREFIX) if compression['class']
973
1253
 
974
- Table::Options.new(
1254
+ Cassandra::ColumnContainer::Options.new(
975
1255
  table_data['comment'],
976
1256
  table_data['read_repair_chance'],
977
1257
  table_data['dclocal_read_repair_chance'],
@@ -988,76 +1268,146 @@ module Cassandra
988
1268
  table_data['max_index_interval'],
989
1269
  compaction_strategy,
990
1270
  compression,
991
- is_compact
1271
+ is_compact,
1272
+ table_data['crc_check_chance'],
1273
+ table_data['extensions']
992
1274
  )
993
1275
  end
994
1276
 
995
1277
  def create_column(column_data, types)
996
1278
  name = column_data['column_name']
997
- is_static = (column_data['kind'].to_s.upcase == 'STATIC')
1279
+ is_static = column_data['kind'].to_s.casecmp('STATIC').zero?
998
1280
  order = column_data['clustering_order'] == 'desc' ? :desc : :asc
999
- type, is_frozen = @type_parser.parse(column_data['type'], types)
1281
+ if column_data['type'][0] == "'"
1282
+ # This is a custom column type.
1283
+ type = Types.custom(column_data['type'].slice(1, column_data['type'].length - 2))
1284
+ is_frozen = false
1285
+ else
1286
+ type, is_frozen = @type_parser.parse(column_data['type'], types)
1287
+ end
1000
1288
 
1001
- Column.new(name, type, order, nil, is_static, is_frozen)
1289
+ Column.new(name, type, order, is_static, is_frozen)
1002
1290
  end
1003
1291
 
1004
- def create_table(table_data, rows_columns, types = nil)
1292
+ def create_table(table_data, rows_columns, rows_indexes, types = nil)
1005
1293
  keyspace_name = table_data['keyspace_name']
1006
1294
  table_name = table_data['table_name']
1007
1295
  table_flags = table_data['flags']
1008
- table_columns = {}
1009
- other_columns = []
1010
- clustering_size = 0
1011
1296
 
1012
1297
  is_dense = table_flags.include?('dense')
1013
1298
  is_super = table_flags.include?('super')
1014
1299
  is_compound = table_flags.include?('compound')
1015
1300
  is_compact = is_super || is_dense || !is_compound
1301
+ is_static_compact = !is_super && !is_dense && !is_compound
1016
1302
 
1303
+ # Separate out partition-key, clustering columns, other columns.
1017
1304
  partition_key = []
1018
1305
  clustering_columns = []
1019
1306
  clustering_order = []
1020
- types ||= @schema.keyspace(keyspace_name).send(:raw_types)
1307
+ other_columns = []
1308
+ types ||= @schema.keyspace(keyspace_name).send(:raw_types)
1021
1309
 
1022
1310
  rows_columns.each do |row|
1023
1311
  next if row['column_name'].empty?
1024
1312
 
1025
- column = create_column(row, types)
1026
1313
  kind = row['kind'].to_s
1027
1314
  index = row['position'] || 0
1028
1315
 
1316
+ if is_static_compact
1317
+ if kind.casecmp('CLUSTERING').zero? || kind.casecmp('REGULAR').zero?
1318
+ # Skip clustering columns in static-compact tables; they are internal to C*.
1319
+ # Oddly so are regular columns.
1320
+ next
1321
+ end
1322
+ if kind.casecmp('STATIC').zero?
1323
+ # Coerce static type to regular.
1324
+ kind = 'REGULAR'
1325
+ row['kind'] = 'regular'
1326
+ end
1327
+ end
1328
+
1329
+ column = create_column(row, types)
1029
1330
  case kind.upcase
1030
1331
  when 'PARTITION_KEY'
1031
1332
  partition_key[index] = column
1032
1333
  when 'CLUSTERING'
1033
1334
  clustering_columns[index] = column
1034
1335
  clustering_order[index] = column.order
1035
-
1036
- if clustering_size.zero? || index == clustering_size
1037
- clustering_size = index + 1
1038
- end
1039
1336
  else
1040
1337
  other_columns << column
1041
1338
  end
1042
1339
  end
1043
1340
 
1044
- partition_key.each do |column|
1045
- table_columns[column.name] = column
1341
+ # Default the crc_check_chance to 1.0 (Java driver does this, so we
1342
+ # should, too).
1343
+ table_data['crc_check_chance'] ||= 1.0
1344
+ compaction_strategy = create_compaction_strategy(table_data)
1345
+ table_options =
1346
+ create_table_options(table_data, compaction_strategy, is_compact)
1347
+
1348
+ table = Cassandra::Table.new(@schema.keyspace(keyspace_name),
1349
+ table_name,
1350
+ partition_key,
1351
+ clustering_columns,
1352
+ other_columns,
1353
+ table_options,
1354
+ clustering_order,
1355
+ table_data['id'])
1356
+ rows_indexes.each do |row|
1357
+ create_index(table, row)
1046
1358
  end
1359
+ table
1360
+ end
1047
1361
 
1048
- clustering_columns.each do |column|
1049
- table_columns[column.name] = column
1050
- end
1362
+ def create_index(table, row_index)
1363
+ options = row_index['options']
1364
+ table.add_index(Cassandra::Index.new(table, row_index['index_name'],
1365
+ row_index['kind'].downcase.to_sym,
1366
+ options['target'], options))
1367
+ end
1368
+
1369
+ def create_materialized_view(view_data, rows_columns, base_table, types = nil)
1370
+ keyspace_name = view_data['keyspace_name']
1371
+ view_name = view_data['view_name']
1372
+ include_all_columns = view_data['include_all_columns']
1373
+ where_clause = view_data['where_clause']
1374
+
1375
+ # Separate out partition key, clustering columns, other columns
1376
+ partition_key = []
1377
+ clustering_columns = []
1378
+ other_columns = []
1379
+ types ||= @schema.keyspace(keyspace_name).send(:raw_types)
1380
+
1381
+ rows_columns.each do |row|
1382
+ next if row['column_name'].empty?
1383
+
1384
+ column = create_column(row, types)
1385
+ kind = row['kind'].to_s
1386
+ index = row['position'] || 0
1051
1387
 
1052
- other_columns.each do |column|
1053
- table_columns[column.name] = column
1388
+ case kind.upcase
1389
+ when 'PARTITION_KEY'
1390
+ partition_key[index] = column
1391
+ when 'CLUSTERING'
1392
+ clustering_columns[index] = column
1393
+ else
1394
+ other_columns << column
1395
+ end
1054
1396
  end
1055
1397
 
1056
- compaction_strategy = create_compaction_strategy(table_data)
1057
- table_options = create_table_options(table_data, compaction_strategy, is_compact)
1398
+ compaction_strategy = create_compaction_strategy(view_data)
1399
+ view_options = create_table_options(view_data, compaction_strategy, false)
1058
1400
 
1059
- Table.new(keyspace_name, table_name, partition_key, clustering_columns,
1060
- table_columns, table_options, clustering_order)
1401
+ MaterializedView.new(@schema.keyspace(keyspace_name),
1402
+ view_name,
1403
+ partition_key,
1404
+ clustering_columns,
1405
+ other_columns,
1406
+ view_options,
1407
+ include_all_columns,
1408
+ where_clause,
1409
+ base_table,
1410
+ view_data['id'])
1061
1411
  end
1062
1412
  end
1063
1413
 
@@ -1109,6 +1459,13 @@ module Cassandra
1109
1459
  return Ione::Future.failed(e)
1110
1460
  end
1111
1461
 
1462
+ def fetch_materialized_view(connection, keyspace_name, view_name)
1463
+ find_fetcher(connection)
1464
+ .fetch_materialized_view(connection, keyspace_name, view_name)
1465
+ rescue => e
1466
+ return Ione::Future.failed(e)
1467
+ end
1468
+
1112
1469
  def fetch_type(connection, keyspace_name, type_name)
1113
1470
  find_fetcher(connection)
1114
1471
  .fetch_type(connection, keyspace_name, type_name)
@@ -1130,13 +1487,16 @@ module Cassandra
1130
1487
  return Ione::Future.failed(e)
1131
1488
  end
1132
1489
 
1133
- # parse an array of string argument types and return an array of [Cassandra::Type]s.
1490
+ # parse an array of string argument types and return an array of
1491
+ # [Cassandra::Type]s.
1134
1492
  # @param connection a connection to a Cassandra node.
1135
1493
  # @param keyspace_name [String] name of the keyspace.
1136
1494
  # @param argument_types [Array<String>] array of argument types.
1137
1495
  # @return [Array<Cassandra::Type>] array of parsed types.
1138
1496
  def parse_argument_types(connection, keyspace_name, argument_types)
1139
- find_fetcher(connection).parse_argument_types(connection, keyspace_name, argument_types)
1497
+ find_fetcher(connection).parse_argument_types(connection,
1498
+ keyspace_name,
1499
+ argument_types)
1140
1500
  end
1141
1501
 
1142
1502
  private
@@ -1147,21 +1507,21 @@ module Cassandra
1147
1507
  unless host
1148
1508
  ips = @registry.hosts.map(&:ip)
1149
1509
  raise Errors::ClientError,
1150
- "unable to find release version for current host, " \
1510
+ 'unable to find release version for current host, ' \
1151
1511
  "connected to #{connection.host}, but cluster contains " \
1152
1512
  "#{ips}."
1153
1513
  end
1154
1514
 
1155
1515
  version = host.release_version
1156
1516
  unless version
1157
- raise Errors::ClientError, "unable to determine release " \
1517
+ raise Errors::ClientError, 'unable to determine release ' \
1158
1518
  "version for host: #{host.inspect}"
1159
1519
  end
1160
1520
 
1161
1521
  @fetchers[version] ||= begin
1162
1522
  current = @versions.find {|v| v.matches?(version)}
1163
1523
  unless current
1164
- raise Errors::ClientError, "unsupported release version " \
1524
+ raise Errors::ClientError, 'unsupported release version ' \
1165
1525
  "#{version.inspect}."
1166
1526
  end
1167
1527
  current.fetcher