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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -53
  3. data/lib/cassandra.rb +22 -3
  4. data/lib/cassandra/aggregate.rb +109 -0
  5. data/lib/cassandra/argument.rb +51 -0
  6. data/lib/cassandra/auth/providers/password.rb +7 -4
  7. data/lib/cassandra/cluster.rb +14 -3
  8. data/lib/cassandra/cluster/client.rb +56 -34
  9. data/lib/cassandra/cluster/connector.rb +6 -6
  10. data/lib/cassandra/cluster/control_connection.rb +204 -251
  11. data/lib/cassandra/cluster/metadata.rb +2 -0
  12. data/lib/cassandra/cluster/schema.rb +131 -209
  13. data/lib/cassandra/cluster/schema/cql_type_parser.rb +104 -0
  14. data/lib/cassandra/cluster/schema/fetchers.rb +1174 -0
  15. data/lib/cassandra/cluster/schema/{type_parser.rb → fqcn_type_parser.rb} +7 -3
  16. data/lib/cassandra/column.rb +2 -2
  17. data/lib/cassandra/driver.rb +27 -9
  18. data/lib/cassandra/errors.rb +179 -25
  19. data/lib/cassandra/execution/info.rb +8 -1
  20. data/lib/cassandra/execution/options.rb +34 -0
  21. data/lib/cassandra/execution/trace.rb +42 -10
  22. data/lib/cassandra/function.rb +150 -0
  23. data/lib/cassandra/future.rb +66 -35
  24. data/lib/cassandra/host.rb +7 -4
  25. data/lib/cassandra/keyspace.rb +112 -13
  26. data/lib/cassandra/load_balancing.rb +1 -1
  27. data/lib/cassandra/protocol.rb +9 -3
  28. data/lib/cassandra/protocol/coder.rb +434 -155
  29. data/lib/cassandra/protocol/cql_byte_buffer.rb +43 -0
  30. data/lib/cassandra/protocol/cql_protocol_handler.rb +4 -1
  31. data/lib/cassandra/protocol/request.rb +4 -0
  32. data/lib/cassandra/protocol/requests/auth_response_request.rb +5 -1
  33. data/lib/cassandra/protocol/requests/batch_request.rb +7 -2
  34. data/lib/cassandra/protocol/requests/credentials_request.rb +5 -1
  35. data/lib/cassandra/protocol/requests/execute_request.rb +16 -10
  36. data/lib/cassandra/protocol/requests/prepare_request.rb +12 -3
  37. data/lib/cassandra/protocol/requests/query_request.rb +20 -11
  38. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +4 -4
  39. data/lib/cassandra/protocol/responses/error_response.rb +14 -14
  40. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +41 -0
  41. data/lib/cassandra/protocol/responses/prepared_result_response.rb +12 -9
  42. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +5 -3
  43. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +43 -0
  44. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +4 -4
  45. data/lib/cassandra/protocol/responses/ready_response.rb +5 -1
  46. data/lib/cassandra/protocol/responses/result_response.rb +3 -3
  47. data/lib/cassandra/protocol/responses/rows_result_response.rb +2 -2
  48. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +25 -24
  49. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +20 -23
  50. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
  51. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +4 -4
  52. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +4 -4
  53. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +45 -0
  54. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +4 -4
  55. data/lib/cassandra/protocol/v1.rb +38 -13
  56. data/lib/cassandra/protocol/v3.rb +34 -29
  57. data/lib/cassandra/protocol/v4.rb +334 -0
  58. data/lib/cassandra/result.rb +10 -9
  59. data/lib/cassandra/retry.rb +17 -3
  60. data/lib/cassandra/retry/policies/default.rb +9 -3
  61. data/lib/cassandra/session.rb +15 -7
  62. data/lib/cassandra/statement.rb +5 -0
  63. data/lib/cassandra/statements/batch.rb +36 -12
  64. data/lib/cassandra/statements/bound.rb +2 -1
  65. data/lib/cassandra/statements/prepared.rb +106 -35
  66. data/lib/cassandra/statements/simple.rb +4 -2
  67. data/lib/cassandra/table.rb +70 -105
  68. data/lib/cassandra/time.rb +98 -0
  69. data/lib/cassandra/time_uuid.rb +1 -1
  70. data/lib/cassandra/tuple.rb +7 -0
  71. data/lib/cassandra/types.rb +472 -272
  72. data/lib/cassandra/udt.rb +10 -0
  73. data/lib/cassandra/util.rb +32 -1
  74. data/lib/cassandra/uuid.rb +6 -1
  75. data/lib/cassandra/uuid/generator.rb +7 -7
  76. data/lib/cassandra/version.rb +1 -1
  77. data/lib/cassandra_murmur3.jar +0 -0
  78. data/lib/datastax/cassandra.rb +5 -2
  79. metadata +27 -17
@@ -30,6 +30,8 @@ module Cassandra
30
30
  @partitioners = schema_partitioners
31
31
  @strategies = replication_strategies
32
32
  @default_strategy = default_replication_strategy
33
+ @token_replicas = ::Hash.new
34
+ @token_ring = ::Array.new
33
35
  end
34
36
 
35
37
  def find_replicas(keyspace, statement)
@@ -22,17 +22,33 @@ module Cassandra
22
22
  class Schema
23
23
  include MonitorMixin
24
24
 
25
- def initialize(schema_type_parser)
26
- @type_parser = schema_type_parser
27
- @keyspaces = ::Hash.new
28
- @listeners = ::Set.new
25
+ def initialize
26
+ @keyspaces = ::Hash.new
27
+ @listeners = ::Set.new
29
28
 
30
29
  mon_initialize
31
30
  end
32
31
 
33
- def create_partition_key(keyspace, table, values)
34
- keyspace = @keyspaces[keyspace]
35
- keyspace && keyspace.create_partition_key(table, values)
32
+ def get_pk_idx(metadata)
33
+ return EMPTY_LIST unless metadata
34
+
35
+ keyspace_name, table_name, _ = metadata.first
36
+ return EMPTY_LIST unless keyspace_name && table_name
37
+
38
+ keyspace = @keyspaces[keyspace_name]
39
+ return EMPTY_LIST unless keyspace
40
+
41
+ table = keyspace.table(table_name)
42
+ return EMPTY_LIST unless table
43
+
44
+ partition_key = table.partition_key
45
+ return EMPTY_LIST unless partition_key && partition_key.size <= metadata.size
46
+
47
+ partition_key.map do |column|
48
+ i = metadata.index {|(_, _, name, _)| name == column.name}
49
+ return EMPTY_LIST if i.nil?
50
+ i
51
+ end
36
52
  end
37
53
 
38
54
  def add_listener(listener)
@@ -51,25 +67,13 @@ module Cassandra
51
67
  self
52
68
  end
53
69
 
54
- def update_keyspaces(host, keyspaces, tables, columns, types)
55
- columns = columns.each_with_object(deephash { [] }) do |row, index|
56
- index[row['keyspace_name']] << row
57
- end
58
-
59
- tables = tables.each_with_object(deephash { [] }) do |row, index|
60
- index[row['keyspace_name']] << row
61
- end
62
-
63
- types = types.each_with_object(deephash { [] }) do |row, index|
64
- index[row['keyspace_name']] << row
65
- end
66
-
70
+ def replace(keyspaces)
67
71
  current_keyspaces = ::Set.new
68
72
 
69
- keyspaces.each do |row|
70
- current_keyspaces << keyspace = row['keyspace_name']
73
+ keyspaces.each do |keyspace|
74
+ current_keyspaces << keyspace.name
71
75
 
72
- update_keyspace(host, row, tables[keyspace], columns[keyspace], types[keyspace])
76
+ replace_keyspace(keyspace)
73
77
  end
74
78
 
75
79
  @keyspaces.each do |name, keyspace|
@@ -79,40 +83,21 @@ module Cassandra
79
83
  self
80
84
  end
81
85
 
82
- def update_keyspace(host, keyspace, tables, columns, types)
83
- keyspace_name = keyspace['keyspace_name']
86
+ def replace_keyspace(keyspace)
87
+ old_keyspace = @keyspaces[keyspace.name]
84
88
 
85
- columns = columns.each_with_object(deephash { ::Hash.new }) do |row, index|
86
- index[row['columnfamily_name']][row['column_name']] = row
87
- end
88
-
89
- tables = tables.each_with_object(Hash.new) do |row, index|
90
- name = row['columnfamily_name']
91
- index[name] = create_table(row, columns[name], host.release_version)
92
- end
93
-
94
- types = types.each_with_object(Hash.new) do |row, index|
95
- name = row['type_name']
96
- index[name] = create_type(row, host.release_version)
97
- end
98
-
99
- replication = Keyspace::Replication.new(keyspace['strategy_class'], ::JSON.load(keyspace['strategy_options']))
100
- keyspace = Keyspace.new(keyspace_name, keyspace['durable_writes'], replication, tables, types)
101
-
102
- return self if keyspace == @keyspaces[keyspace_name]
103
-
104
- created = !@keyspaces.include?(keyspace_name)
89
+ return self if old_keyspace == keyspace
105
90
 
106
91
  synchronize do
107
92
  keyspaces = @keyspaces.dup
108
- keyspaces[keyspace_name] = keyspace
93
+ keyspaces[keyspace.name] = keyspace
109
94
  @keyspaces = keyspaces
110
95
  end
111
96
 
112
- if created
113
- keyspace_created(keyspace)
114
- else
97
+ if old_keyspace
115
98
  keyspace_changed(keyspace)
99
+ else
100
+ keyspace_created(keyspace)
116
101
  end
117
102
 
118
103
  self
@@ -134,20 +119,20 @@ module Cassandra
134
119
  self
135
120
  end
136
121
 
137
- def update_table(host, keyspace_name, table, columns)
138
- keyspace = @keyspaces[keyspace_name]
122
+ def replace_table(table)
123
+ keyspace = @keyspaces[table.keyspace]
139
124
 
140
125
  return self unless keyspace
141
126
 
142
- columns = columns.each_with_object(::Hash.new) do |row, index|
143
- index[row['column_name']] = row
144
- end
145
- table = create_table(table, columns, host.release_version)
127
+ old_table = keyspace.table(table.name)
128
+
129
+ return self if old_table == table
130
+
146
131
  keyspace = keyspace.update_table(table)
147
132
 
148
133
  synchronize do
149
134
  keyspaces = @keyspaces.dup
150
- keyspaces[keyspace_name] = keyspace
135
+ keyspaces[keyspace.name] = keyspace
151
136
  @keyspaces = keyspaces
152
137
  end
153
138
 
@@ -161,6 +146,10 @@ module Cassandra
161
146
 
162
147
  return self unless keyspace
163
148
 
149
+ table = keyspace.table(table_name)
150
+
151
+ return self unless table
152
+
164
153
  keyspace = keyspace.delete_table(table_name)
165
154
 
166
155
  synchronize do
@@ -174,17 +163,20 @@ module Cassandra
174
163
  self
175
164
  end
176
165
 
177
- def update_type(host, keyspace_name, type)
178
- keyspace = @keyspaces[keyspace_name]
166
+ def replace_type(type)
167
+ keyspace = @keyspaces[type.keyspace]
179
168
 
180
169
  return self unless keyspace
181
170
 
182
- type = create_type(type, host.release_version)
171
+ old_type = keyspace.type(type.name)
172
+
173
+ return self if old_type == type
174
+
183
175
  keyspace = keyspace.update_type(type)
184
176
 
185
177
  synchronize do
186
178
  keyspaces = @keyspaces.dup
187
- keyspaces[keyspace_name] = keyspace
179
+ keyspaces[keyspace.name] = keyspace
188
180
  @keyspaces = keyspaces
189
181
  end
190
182
 
@@ -198,6 +190,10 @@ module Cassandra
198
190
 
199
191
  return self unless keyspace
200
192
 
193
+ type = keyspace.type(type_name)
194
+
195
+ return self unless type
196
+
201
197
  keyspace = keyspace.delete_type(type_name)
202
198
 
203
199
  synchronize do
@@ -211,189 +207,113 @@ module Cassandra
211
207
  self
212
208
  end
213
209
 
214
- def has_keyspace?(name)
215
- @keyspaces.include?(name)
216
- end
210
+ def replace_function(function)
211
+ keyspace = @keyspaces[function.keyspace]
217
212
 
218
- def keyspace(name)
219
- @keyspaces[name]
220
- end
221
-
222
- def each_keyspace(&block)
223
- if block_given?
224
- @keyspaces.each_value(&block)
225
- self
226
- else
227
- @keyspaces.values
228
- end
229
- end
230
- alias :keyspaces :each_keyspace
213
+ return self unless keyspace
231
214
 
232
- private
215
+ old_function = keyspace.function(function.name, *function.argument_types)
233
216
 
234
- def create_type(type, version)
235
- keyspace = type['keyspace_name']
236
- name = type['type_name']
237
- fields = ::Array.new
217
+ return self if old_function == function
238
218
 
239
- type['field_names'].zip(type['field_types']) do |(field_name, field_type)|
240
- field_type = @type_parser.parse(field_type).results.first.first
219
+ keyspace = keyspace.update_function(function)
241
220
 
242
- fields << [field_name, field_type]
221
+ synchronize do
222
+ keyspaces = @keyspaces.dup
223
+ keyspaces[keyspace.name] = keyspace
224
+ @keyspaces = keyspaces
243
225
  end
244
226
 
245
- Types.udt(keyspace, name, fields)
227
+ keyspace_changed(keyspace)
228
+
229
+ self
246
230
  end
247
231
 
248
- def create_table(table, columns, version)
249
- keyspace = table['keyspace_name']
250
- name = table['columnfamily_name']
251
- key_validator = @type_parser.parse(table['key_validator'])
252
- comparator = @type_parser.parse(table['comparator'])
253
- column_aliases = ::JSON.load(table['column_aliases'])
232
+ def delete_function(keyspace_name, function_name, function_arg_types)
233
+ keyspace = @keyspaces[keyspace_name]
234
+
235
+ return self unless keyspace
254
236
 
255
- clustering_size = find_clustering_size(comparator, columns.values,
256
- column_aliases, version)
237
+ function = keyspace.function(function_name, *function_arg_types)
257
238
 
258
- is_dense = clustering_size != comparator.results.size - 1
259
- is_compact = is_dense || !comparator.collections
260
- partition_key = []
261
- clustering_columns = []
262
- clustering_order = []
239
+ return self unless function
263
240
 
264
- compaction_strategy = Table::Compaction.new(
265
- table['compaction_strategy_class'],
266
- ::JSON.load(table['compaction_strategy_options'])
267
- )
268
- compression_parameters = ::JSON.load(table['compression_parameters'])
241
+ keyspace = keyspace.delete_function(function_name, function_arg_types)
269
242
 
270
- options = Table::Options.new(table, compaction_strategy, compression_parameters, is_compact, version)
271
- columns = create_columns(key_validator, comparator, column_aliases, is_dense, clustering_size, table, columns, version, partition_key, clustering_columns, clustering_order)
243
+ synchronize do
244
+ keyspaces = @keyspaces.dup
245
+ keyspaces[keyspace_name] = keyspace
246
+ @keyspaces = keyspaces
247
+ end
248
+
249
+ keyspace_changed(keyspace)
272
250
 
273
- Table.new(keyspace, name, partition_key, clustering_columns, columns, options, clustering_order, version)
251
+ self
274
252
  end
275
253
 
276
- def find_clustering_size(comparator, columns, aliases, cassandra_version)
277
- if cassandra_version.start_with?('1')
278
- if comparator.collections
279
- size = comparator.results.size
280
- (!comparator.collections.empty? || aliases.size == size - 1 && comparator.results.last.first == :text) ? size - 1 : size
281
- else
282
- (!aliases.empty? || columns.empty?) ? 1 : 0
283
- end
284
- else
285
- max_index = nil
254
+ def replace_aggregate(aggregate)
255
+ keyspace = @keyspaces[aggregate.keyspace]
256
+
257
+ return self unless keyspace
286
258
 
287
- columns.each do |cl|
288
- if cl['type'].to_s.upcase == 'CLUSTERING_KEY'
289
- index = cl['component_index'] || 0
259
+ old_aggregate = keyspace.aggregate(aggregate.name, *aggregate.argument_types)
290
260
 
291
- if max_index.nil? || index > max_index
292
- max_index = index
293
- end
294
- end
295
- end
261
+ return self if old_aggregate == aggregate
296
262
 
297
- return 0 if max_index.nil?
263
+ keyspace = keyspace.update_aggregate(aggregate)
298
264
 
299
- max_index + 1
265
+ synchronize do
266
+ keyspaces = @keyspaces.dup
267
+ keyspaces[keyspace.name] = keyspace
268
+ @keyspaces = keyspaces
300
269
  end
270
+
271
+ keyspace_changed(keyspace)
272
+
273
+ self
301
274
  end
302
275
 
303
- def create_columns(key_validator, comparator, column_aliases, is_dense, clustering_size, table, columns, cassandra_version, partition_key, clustering_columns, clustering_order)
304
- table_columns = {}
305
- other_columns = []
306
-
307
- if cassandra_version.start_with?('1')
308
- key_aliases = ::JSON.load(table['key_aliases'])
309
-
310
- key_validator.results.each_with_index do |(type, order, is_frozen), i|
311
- key_alias = key_aliases.fetch(i) { i.zero? ? "key" : "key#{i + 1}" }
312
-
313
- partition_key[i] = Column.new(key_alias, type, order, nil, false, is_frozen)
314
- end
315
-
316
- if comparator.results.size > 1
317
- clustering_size.times do |i|
318
- column_alias = column_aliases.fetch(i) { "column#{i + 1}" }
319
- type, order, is_frozen = comparator.results.fetch(i)
320
-
321
- clustering_columns[i] = Column.new(column_alias, type, order, nil, false, is_frozen)
322
- clustering_order[i] = order
323
- end
324
- else
325
- column_alias = column_aliases.first || "column1"
326
- type, order, is_frozen = comparator.results.first
327
-
328
- clustering_columns[0] = Column.new(column_alias, type, order, nil, false, is_frozen)
329
- clustering_order[0] = order
330
- end
331
-
332
- if is_dense
333
- value_alias = table['value_alias']
334
- value_alias = 'value' if value_alias.nil? || value_alias.empty?
335
- type, order, is_frozen = @type_parser.parse(table['default_validator']).results.first
336
- other_columns << Column.new(value_alias, type, order, nil, false, is_frozen)
337
- end
338
-
339
- columns.each do |name, row|
340
- other_columns << create_column(row)
341
- end
342
- else
343
- columns.each do |name, row|
344
- next if row['column_name'].empty?
345
-
346
- column = create_column(row)
347
- type = row['type'].to_s
348
- index = row['component_index'] || 0
349
-
350
- case type.upcase
351
- when 'PARTITION_KEY'
352
- partition_key[index] = column
353
- when 'CLUSTERING_KEY'
354
- clustering_columns[index] = column
355
- clustering_order[index] = column.order
356
- else
357
- other_columns << column
358
- end
359
- end
360
- end
276
+ def delete_aggregate(keyspace_name, aggregate_name, aggregate_arg_types)
277
+ keyspace = @keyspaces[keyspace_name]
361
278
 
362
- partition_key.each do |column|
363
- table_columns[column.name] = column
364
- end
279
+ return self unless keyspace
365
280
 
366
- clustering_columns.each do |column|
367
- table_columns[column.name] = column
368
- end
281
+ aggregate = keyspace.aggregate(aggregate_name, *aggregate_arg_types)
282
+
283
+ return self unless aggregate
369
284
 
370
- other_columns.each do |column|
371
- table_columns[column.name] = column
285
+ keyspace = keyspace.delete_aggregate(aggregate_name, aggregate_arg_types)
286
+
287
+ synchronize do
288
+ keyspaces = @keyspaces.dup
289
+ keyspaces[keyspace_name] = keyspace
290
+ @keyspaces = keyspaces
372
291
  end
373
292
 
374
- table_columns
293
+ keyspace_changed(keyspace)
294
+
295
+ self
296
+ end
297
+
298
+ def has_keyspace?(name)
299
+ @keyspaces.include?(name)
375
300
  end
376
301
 
377
- def create_column(column)
378
- name = column['column_name']
379
- type, order, is_frozen = @type_parser.parse(column['validator']).results.first
380
- is_static = (column['type'] == 'STATIC')
302
+ def keyspace(name)
303
+ @keyspaces[name]
304
+ end
381
305
 
382
- if column['index_type'].nil?
383
- index = nil
384
- elsif column['index_type'].to_s.upcase == 'CUSTOM' || !column['index_options']
385
- index = Column::Index.new(column['index_name'])
306
+ def each_keyspace(&block)
307
+ if block_given?
308
+ @keyspaces.each_value(&block)
309
+ self
386
310
  else
387
- options = ::JSON.load(column['index_options'])
388
- index = Column::Index.new(column['index_name'], options && options['class_name'])
311
+ @keyspaces.values
389
312
  end
390
-
391
- Column.new(name, type, order, index, is_static, is_frozen)
392
313
  end
314
+ alias :keyspaces :each_keyspace
393
315
 
394
- def deephash
395
- ::Hash.new {|hash, key| hash[key] = yield}
396
- end
316
+ private
397
317
 
398
318
  def keyspace_created(keyspace)
399
319
  @listeners.each do |listener|
@@ -416,6 +336,8 @@ module Cassandra
416
336
  end
417
337
  end
418
338
 
339
+ require 'cassandra/cluster/schema/cql_type_parser'
340
+ require 'cassandra/cluster/schema/fetchers'
419
341
  require 'cassandra/cluster/schema/partitioners'
420
342
  require 'cassandra/cluster/schema/replication_strategies'
421
- require 'cassandra/cluster/schema/type_parser'
343
+ require 'cassandra/cluster/schema/fqcn_type_parser'