cassandra-driver 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +46 -31
  3. data/lib/cassandra.rb +35 -44
  4. data/lib/cassandra/cluster.rb +40 -11
  5. data/lib/cassandra/cluster/client.rb +193 -159
  6. data/lib/cassandra/cluster/connector.rb +12 -10
  7. data/lib/cassandra/cluster/control_connection.rb +38 -10
  8. data/lib/cassandra/cluster/options.rb +8 -4
  9. data/lib/cassandra/cluster/registry.rb +1 -2
  10. data/lib/cassandra/cluster/schema/fetchers.rb +122 -26
  11. data/lib/cassandra/column_container.rb +9 -4
  12. data/lib/cassandra/custom_data.rb +24 -22
  13. data/lib/cassandra/driver.rb +30 -13
  14. data/lib/cassandra/errors.rb +12 -2
  15. data/lib/cassandra/execution/options.rb +52 -16
  16. data/lib/cassandra/execution/profile.rb +150 -0
  17. data/lib/cassandra/execution/profile_manager.rb +71 -0
  18. data/lib/cassandra/execution/trace.rb +5 -4
  19. data/lib/cassandra/executors.rb +1 -1
  20. data/lib/cassandra/index.rb +1 -1
  21. data/lib/cassandra/keyspace.rb +36 -1
  22. data/lib/cassandra/protocol.rb +5 -0
  23. data/lib/cassandra/protocol/coder.rb +2 -1
  24. data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -0
  25. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +10 -4
  26. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +14 -8
  27. data/lib/cassandra/protocol/v3.rb +2 -1
  28. data/lib/cassandra/protocol/v4.rb +58 -20
  29. data/lib/cassandra/result.rb +1 -1
  30. data/lib/cassandra/session.rb +43 -16
  31. data/lib/cassandra/statements/bound.rb +5 -1
  32. data/lib/cassandra/statements/prepared.rb +8 -3
  33. data/lib/cassandra/table.rb +72 -0
  34. data/lib/cassandra/trigger.rb +67 -0
  35. data/lib/cassandra/types.rb +12 -24
  36. data/lib/cassandra/udt.rb +3 -6
  37. data/lib/cassandra/uuid/generator.rb +6 -3
  38. data/lib/cassandra/version.rb +1 -1
  39. metadata +5 -2
@@ -122,11 +122,8 @@ module Cassandra
122
122
  ssl: @connection_options.ssl) do |connection|
123
123
  raise Errors::ClientError, 'Not connected, reactor stopped' unless connection
124
124
 
125
- if @connection_options.nodelay?
126
- connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
127
- else
128
- connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 0)
129
- end
125
+ connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY,
126
+ @connection_options.nodelay? ? 1 : 0)
130
127
 
131
128
  Protocol::CqlProtocolHandler.new(connection,
132
129
  @reactor,
@@ -225,10 +222,12 @@ module Cassandra
225
222
  ::Ione::Future.resolved(connection)
226
223
  when Protocol::ErrorResponse
227
224
  ::Ione::Future.failed(
228
- r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :one, 0))
225
+ r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :one, 0)
226
+ )
229
227
  else
230
228
  ::Ione::Future.failed(
231
- Errors::InternalError.new("Unexpected response #{r.inspect}"))
229
+ Errors::InternalError.new("Unexpected response #{r.inspect}")
230
+ )
232
231
  end
233
232
  end
234
233
  end
@@ -244,7 +243,8 @@ module Cassandra
244
243
  VOID_OPTIONS,
245
244
  EMPTY_LIST,
246
245
  :one,
247
- 0)
246
+ 0
247
+ )
248
248
  end
249
249
 
250
250
  def request_options(connection)
@@ -291,10 +291,12 @@ module Cassandra
291
291
  ::Ione::Future.resolved(connection)
292
292
  when Protocol::ErrorResponse
293
293
  ::Ione::Future.failed(
294
- r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :one, 0))
294
+ r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :one, 0)
295
+ )
295
296
  else
296
297
  ::Ione::Future.failed(
297
- Errors::InternalError.new("Unexpected response #{r.inspect}"))
298
+ Errors::InternalError.new("Unexpected response #{r.inspect}")
299
+ )
298
300
  end
299
301
  end
300
302
  end
@@ -36,8 +36,10 @@ module Cassandra
36
36
  @address_resolver = address_resolution_policy
37
37
  @connector = connector
38
38
  @connection_options = connection_options
39
+ @connection = nil
39
40
  @schema_fetcher = schema_fetcher
40
41
  @refreshing_statuses = ::Hash.new(false)
42
+ @refresh_schema_future = nil
41
43
  @status = :closed
42
44
  @refreshing_hosts = false
43
45
  @refreshing_host = ::Hash.new(false)
@@ -88,7 +90,8 @@ module Cassandra
88
90
  (@status == :closing || @status == :closed) ||
89
91
  @load_balancing_policy.distance(host) == :ignore
90
92
  return connect_to_first_available(
91
- @load_balancing_policy.plan(nil, VOID_STATEMENT, VOID_OPTIONS))
93
+ @load_balancing_policy.plan(nil, VOID_STATEMENT, VOID_OPTIONS)
94
+ )
92
95
  end
93
96
  end
94
97
 
@@ -146,18 +149,20 @@ module Cassandra
146
149
 
147
150
  private
148
151
 
149
- SELECT_LOCAL = Protocol::QueryRequest.new(
152
+ SELECT_LOCAL = Protocol::QueryRequest.new(
150
153
  'SELECT * ' \
151
154
  'FROM system.local',
152
155
  EMPTY_LIST,
153
156
  EMPTY_LIST,
154
- :one)
155
- SELECT_PEERS = Protocol::QueryRequest.new(
157
+ :one
158
+ )
159
+ SELECT_PEERS = Protocol::QueryRequest.new(
156
160
  'SELECT * ' \
157
161
  'FROM system.peers',
158
162
  EMPTY_LIST,
159
163
  EMPTY_LIST,
160
- :one)
164
+ :one
165
+ )
161
166
 
162
167
  SELECT_PEER_QUERY =
163
168
  'SELECT * ' \
@@ -229,7 +234,9 @@ module Cassandra
229
234
  refresh_schema_async_wrapper
230
235
  end
231
236
  when 'DOWN'
232
- @registry.host_down(event.address)
237
+ # RUBY-164: Don't mark host down if there are active connections. We have
238
+ # logic in connector.rb to call host_down when all connections to a node are lost,
239
+ # so that covers the requirement.
233
240
  when 'NEW_NODE'
234
241
  address = event.address
235
242
 
@@ -445,7 +452,7 @@ module Cassandra
445
452
 
446
453
  peers.shuffle!
447
454
  peers.each do |data|
448
- ip = peer_ip(data)
455
+ ip = peer_ip(data, connection.host)
449
456
  next unless ip
450
457
  ips << ip
451
458
  @registry.host_found(ip, data)
@@ -665,9 +672,30 @@ Control connection failed and is unlikely to recover.
665
672
  @connector.connect(host)
666
673
  end
667
674
 
668
- def peer_ip(data)
669
- ip = data['rpc_address']
670
- ip = data['peer'] if ip == '0.0.0.0'
675
+ def peer_ip(data, host_address)
676
+ peer = data['peer']
677
+
678
+ return nil unless peer && data['host_id'] && data['data_center'] && data['rack'] && data['tokens']
679
+
680
+ rpc_address = data['rpc_address']
681
+
682
+ if rpc_address.nil?
683
+ @logger.info("The system.peers row for '#{data['peer']}' has no rpc_address. This is likely " \
684
+ 'a gossip or snitch issue. This host will be ignored.')
685
+ return nil
686
+ end
687
+
688
+ if peer == host_address || rpc_address == host_address
689
+ # Some DSE versions were inserting a line for the local node in peers (with mostly null values).
690
+ # This has been fixed, but if we detect that's the case, ignore it as it's not really a big deal.
691
+
692
+ @logger.debug("System.peers on node #{host_address} has a line for itself. This is not normal but is a " \
693
+ 'known problem of some DSE versions. Ignoring the entry.')
694
+ return nil
695
+ end
696
+
697
+ ip = rpc_address
698
+ ip = peer if ip == '0.0.0.0'
671
699
 
672
700
  @address_resolver.resolve(ip)
673
701
  end
@@ -25,7 +25,7 @@ module Cassandra
25
25
  attr_reader :auth_provider, :compressor, :connect_timeout, :credentials,
26
26
  :heartbeat_interval, :idle_timeout, :port, :schema_refresh_delay,
27
27
  :schema_refresh_timeout, :ssl, :custom_type_handlers
28
- attr_boolean :protocol_negotiable, :synchronize_schema, :nodelay
28
+ attr_boolean :protocol_negotiable, :synchronize_schema, :nodelay, :allow_beta_protocol
29
29
 
30
30
  attr_accessor :protocol_version
31
31
 
@@ -46,7 +46,8 @@ module Cassandra
46
46
  schema_refresh_timeout,
47
47
  nodelay,
48
48
  requests_per_connection,
49
- custom_types)
49
+ custom_types,
50
+ allow_beta_protocol)
50
51
  @logger = logger
51
52
  @protocol_version = protocol_version
52
53
  @credentials = credentials
@@ -61,6 +62,7 @@ module Cassandra
61
62
  @schema_refresh_delay = schema_refresh_delay
62
63
  @schema_refresh_timeout = schema_refresh_timeout
63
64
  @nodelay = nodelay
65
+ @allow_beta_protocol = allow_beta_protocol
64
66
  @custom_type_handlers = {}
65
67
  custom_types.each do |type_klass|
66
68
  @custom_type_handlers[type_klass.type] = type_klass
@@ -71,12 +73,14 @@ module Cassandra
71
73
  @requests_per_connection = requests_per_connection
72
74
 
73
75
  # If @protocol_version is nil, it means we want the driver to negotiate the
74
- # protocol starting with our known max (4). If @protocol_version is not nil,
76
+ # protocol starting with our known max. If @protocol_version is not nil,
75
77
  # it means the user wants us to use a particular version, so we should not
76
78
  # support negotiation.
77
79
 
78
80
  @protocol_negotiable = @protocol_version.nil?
79
- @protocol_version ||= 4
81
+ @protocol_version ||= allow_beta_protocol ?
82
+ Cassandra::Protocol::Versions::BETA_VERSION :
83
+ Cassandra::Protocol::Versions::MAX_SUPPORTED_VERSION
80
84
  end
81
85
 
82
86
  def compression
@@ -170,8 +170,7 @@ module Cassandra
170
170
  Array(data['tokens']).freeze,
171
171
  :up,
172
172
  data['broadcast_address'],
173
- data['listen_address']
174
- )
173
+ data['listen_address'])
175
174
  end
176
175
 
177
176
  def toggle_up(host)
@@ -34,8 +34,9 @@ module Cassandra
34
34
  select_functions(connection),
35
35
  select_aggregates(connection),
36
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|
37
+ select_indexes(connection),
38
+ select_triggers(connection))
39
+ .map do |rows_keyspaces, rows_tables, rows_columns, rows_types, rows_functions, rows_aggregates, rows_views, rows_indexes, rows_triggers|
39
40
  lookup_tables = map_rows_by(rows_tables, 'keyspace_name')
40
41
  lookup_columns = map_rows_by(rows_columns, 'keyspace_name')
41
42
  lookup_types = map_rows_by(rows_types, 'keyspace_name')
@@ -43,6 +44,7 @@ module Cassandra
43
44
  lookup_aggregates = map_rows_by(rows_aggregates, 'keyspace_name')
44
45
  lookup_views = map_rows_by(rows_views, 'keyspace_name')
45
46
  lookup_indexes = map_rows_by(rows_indexes, 'keyspace_name')
47
+ lookup_triggers = map_rows_by(rows_triggers, 'keyspace_name')
46
48
 
47
49
  rows_keyspaces.map do |keyspace_data|
48
50
  name = keyspace_data['keyspace_name']
@@ -54,7 +56,8 @@ module Cassandra
54
56
  lookup_functions[name],
55
57
  lookup_aggregates[name],
56
58
  lookup_views[name],
57
- lookup_indexes[name])
59
+ lookup_indexes[name],
60
+ lookup_triggers[name])
58
61
  end
59
62
  end
60
63
  end
@@ -67,8 +70,9 @@ module Cassandra
67
70
  select_keyspace_functions(connection, keyspace_name),
68
71
  select_keyspace_aggregates(connection, keyspace_name),
69
72
  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|
73
+ select_keyspace_indexes(connection, keyspace_name),
74
+ select_keyspace_triggers(connection, keyspace_name))
75
+ .map do |rows_keyspaces, rows_tables, rows_columns, rows_types, rows_functions, rows_aggregates, rows_views, rows_indexes, rows_triggers|
72
76
  if rows_keyspaces.empty?
73
77
  nil
74
78
  else
@@ -79,7 +83,8 @@ module Cassandra
79
83
  rows_functions,
80
84
  rows_aggregates,
81
85
  rows_views,
82
- rows_indexes)
86
+ rows_indexes,
87
+ rows_triggers)
83
88
  end
84
89
  end
85
90
  end
@@ -87,14 +92,16 @@ module Cassandra
87
92
  def fetch_table(connection, keyspace_name, table_name)
88
93
  Ione::Future.all(select_table(connection, keyspace_name, table_name),
89
94
  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)|
95
+ select_table_indexes(connection, keyspace_name, table_name),
96
+ select_table_triggers(connection, keyspace_name, table_name))
97
+ .map do |(rows_tables, rows_columns, rows_indexes, rows_triggers)|
92
98
  if rows_tables.empty?
93
99
  nil
94
100
  else
95
101
  create_table(rows_tables.first,
96
102
  rows_columns,
97
- rows_indexes)
103
+ rows_indexes,
104
+ rows_triggers)
98
105
  end
99
106
  end
100
107
  end
@@ -168,6 +175,10 @@ module Cassandra
168
175
  FUTURE_EMPTY_LIST
169
176
  end
170
177
 
178
+ def select_triggers(connection)
179
+ FUTURE_EMPTY_LIST
180
+ end
181
+
171
182
  def select_types(connection)
172
183
  FUTURE_EMPTY_LIST
173
184
  end
@@ -200,6 +211,10 @@ module Cassandra
200
211
  FUTURE_EMPTY_LIST
201
212
  end
202
213
 
214
+ def select_keyspace_triggers(connection, keyspace_name)
215
+ FUTURE_EMPTY_LIST
216
+ end
217
+
203
218
  def select_keyspace_types(connection, keyspace_name)
204
219
  FUTURE_EMPTY_LIST
205
220
  end
@@ -228,6 +243,10 @@ module Cassandra
228
243
  FUTURE_EMPTY_LIST
229
244
  end
230
245
 
246
+ def select_table_triggers(connection, keyspace_name, table_name)
247
+ FUTURE_EMPTY_LIST
248
+ end
249
+
231
250
  def select_type(connection, keyspace_name, type_name)
232
251
  FUTURE_EMPTY_LIST
233
252
  end
@@ -243,7 +262,8 @@ module Cassandra
243
262
  def send_select_request(connection, cql, params = EMPTY_LIST, types = EMPTY_LIST)
244
263
  backtrace = caller
245
264
  connection.send_request(
246
- Protocol::QueryRequest.new(cql, params, types, :one)).map do |r|
265
+ Protocol::QueryRequest.new(cql, params, types, :one)
266
+ ).map do |r|
247
267
  case r
248
268
  when Protocol::RowsResultResponse
249
269
  r.rows
@@ -348,7 +368,7 @@ module Cassandra
348
368
 
349
369
  def create_keyspace(keyspace_data, rows_tables, rows_columns,
350
370
  rows_types, rows_functions, rows_aggregates,
351
- rows_views, rows_indexes)
371
+ rows_views, rows_indexes, rows_triggers)
352
372
  keyspace_name = keyspace_data['keyspace_name']
353
373
  replication = create_replication(keyspace_data)
354
374
  types = rows_types.each_with_object({}) do |row, h|
@@ -367,10 +387,14 @@ module Cassandra
367
387
  end
368
388
 
369
389
  lookup_columns = map_rows_by(rows_columns, 'columnfamily_name')
390
+ lookup_indexes = map_rows_by(rows_indexes, 'columnfamily_name')
391
+ lookup_triggers = map_rows_by(rows_triggers, 'columnfamily_name')
370
392
  tables = rows_tables.each_with_object({}) do |row, h|
371
393
  table_name = row['columnfamily_name']
372
- # rows_indexes is nil for C* < 3.0.
373
- h[table_name] = create_table(row, lookup_columns[table_name], nil)
394
+ h[table_name] = create_table(row,
395
+ lookup_columns[table_name],
396
+ lookup_indexes[table_name],
397
+ lookup_triggers[table_name])
374
398
  end
375
399
 
376
400
  Keyspace.new(keyspace_name,
@@ -383,7 +407,7 @@ module Cassandra
383
407
  {})
384
408
  end
385
409
 
386
- def create_table(table_data, rows_columns, rows_indexes)
410
+ def create_table(table_data, rows_columns, rows_indexes, rows_triggers)
387
411
  keyspace_name = table_data['keyspace_name']
388
412
  table_name = table_data['columnfamily_name']
389
413
  key_validator = @type_parser.parse(table_data['key_validator'])
@@ -461,7 +485,7 @@ module Cassandra
461
485
  column = create_column(row)
462
486
  other_columns << column
463
487
 
464
- # In C* 1.2.x, index info is in the column metadata; rows_indexes is nil.
488
+ # In C* 1.2.x, index info is in the column metadata; rows_indexes is [].
465
489
  index_rows << [column, row] unless row['index_type'].nil?
466
490
  end
467
491
 
@@ -485,7 +509,8 @@ module Cassandra
485
509
  # Most of this logic was taken from the Java driver.
486
510
  options = {}
487
511
  # For some versions of C*, this field could have a literal string 'null' value.
488
- if !row_column['index_options'].nil? && row_column['index_options'] != 'null' && !row_column['index_options'].empty?
512
+ if !row_column['index_options'].nil? && row_column['index_options'] != 'null' &&
513
+ !row_column['index_options'].empty?
489
514
  options = ::JSON.load(row_column['index_options'])
490
515
  end
491
516
  column_name = Util.escape_name(column.name)
@@ -548,18 +573,24 @@ module Cassandra
548
573
  compression_parameters,
549
574
  is_compact,
550
575
  table_data['crc_check_chance'],
551
- table_data['extensions']
576
+ table_data['extensions'],
577
+ nil
552
578
  )
553
579
  end
554
580
  end
555
581
 
556
582
  class V2_0_x < V1_2_x
583
+ SELECT_TRIGGERS = 'SELECT * FROM system.schema_triggers'.freeze
584
+
557
585
  SELECT_KEYSPACE =
558
586
  'SELECT * FROM system.schema_keyspaces WHERE keyspace_name = ?'.freeze
559
587
  SELECT_KEYSPACE_TABLES =
560
588
  'SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = ?'.freeze
561
589
  SELECT_KEYSPACE_COLUMNS =
562
590
  'SELECT * FROM system.schema_columns WHERE keyspace_name = ?'.freeze
591
+ SELECT_KEYSPACE_TRIGGERS =
592
+ 'SELECT * FROM system.schema_triggers WHERE keyspace_name = ?'.freeze
593
+
563
594
  SELECT_TABLE =
564
595
  'SELECT * ' \
565
596
  'FROM system.schema_columnfamilies ' \
@@ -568,10 +599,14 @@ module Cassandra
568
599
  'SELECT * ' \
569
600
  'FROM system.schema_columns ' \
570
601
  'WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
602
+ SELECT_TABLE_TRIGGERS =
603
+ 'SELECT * ' \
604
+ 'FROM system.schema_triggers ' \
605
+ 'WHERE keyspace_name = ? AND columnfamily_name = ?'.freeze
571
606
 
572
607
  private
573
608
 
574
- def create_table(table_data, rows_columns, rows_indexes)
609
+ def create_table(table_data, rows_columns, rows_indexes, rows_triggers)
575
610
  keyspace_name = table_data['keyspace_name']
576
611
  table_name = table_data['columnfamily_name']
577
612
  comparator = @type_parser.parse(table_data['comparator'])
@@ -598,7 +633,7 @@ module Cassandra
598
633
  clustering_columns[ind] = column
599
634
  clustering_order[ind] = column.order
600
635
 
601
- clustering_size = ind + 1 if clustering_size.zero? || ind == clustering_size
636
+ clustering_size += 1
602
637
  else
603
638
  other_columns << column
604
639
  end
@@ -626,9 +661,21 @@ module Cassandra
626
661
  index_rows.each do |column, row|
627
662
  create_index(table, column, row)
628
663
  end
664
+
665
+ # Create Trigger objects and add them to the table.
666
+ rows_triggers.each do |row_trigger|
667
+ table.add_trigger(Cassandra::Trigger.new(table,
668
+ row_trigger['trigger_name'],
669
+ row_trigger['trigger_options']))
670
+ end
671
+
629
672
  table
630
673
  end
631
674
 
675
+ def select_triggers(connection)
676
+ send_select_request(connection, SELECT_TRIGGERS)
677
+ end
678
+
632
679
  def select_keyspace(connection, keyspace_name)
633
680
  params = [keyspace_name]
634
681
  hints = [Types.varchar]
@@ -647,6 +694,12 @@ module Cassandra
647
694
  send_select_request(connection, SELECT_KEYSPACE_COLUMNS, params, hints)
648
695
  end
649
696
 
697
+ def select_keyspace_triggers(connection, keyspace_name)
698
+ params = [keyspace_name]
699
+ hints = [Types.varchar]
700
+ send_select_request(connection, SELECT_KEYSPACE_TRIGGERS, params, hints)
701
+ end
702
+
650
703
  def select_table(connection, keyspace_name, table_name)
651
704
  params = [keyspace_name, table_name]
652
705
  hints = [Types.varchar, Types.varchar]
@@ -659,6 +712,12 @@ module Cassandra
659
712
  send_select_request(connection, SELECT_TABLE_COLUMNS, params, hints)
660
713
  end
661
714
 
715
+ def select_table_triggers(connection, keyspace_name, table_name)
716
+ params = [keyspace_name, table_name]
717
+ hints = [Types.varchar, Types.varchar]
718
+ send_select_request(connection, SELECT_TABLE_TRIGGERS, params, hints)
719
+ end
720
+
662
721
  def create_table_options(table_data, compaction_strategy, is_compact)
663
722
  compression_parameters = ::JSON.load(table_data['compression_parameters'])
664
723
  if compression_parameters['sstable_compression']
@@ -684,7 +743,8 @@ module Cassandra
684
743
  compression_parameters,
685
744
  is_compact,
686
745
  table_data['crc_check_chance'],
687
- table_data['extensions']
746
+ table_data['extensions'],
747
+ nil
688
748
  )
689
749
  end
690
750
  end
@@ -758,7 +818,8 @@ module Cassandra
758
818
  compression_parameters,
759
819
  is_compact,
760
820
  table_data['crc_check_chance'],
761
- table_data['extensions']
821
+ table_data['extensions'],
822
+ nil
762
823
  )
763
824
  end
764
825
  end
@@ -834,7 +895,9 @@ module Cassandra
834
895
  initial_state = Util.encode_object(
835
896
  Protocol::Coder.read_value_v4(
836
897
  Protocol::CqlByteBuffer.new.append_bytes(aggregate_data['initcond']),
837
- state_type, nil))
898
+ state_type, nil
899
+ )
900
+ )
838
901
 
839
902
  # The state-function takes arguments: first the stype, then the args of the aggregate.
840
903
  state_function = functions.get(aggregate_data['state_func'],
@@ -896,6 +959,7 @@ module Cassandra
896
959
  SELECT_AGGREGATES = 'SELECT * FROM system_schema.aggregates'.freeze
897
960
  SELECT_INDEXES = 'SELECT * FROM system_schema.indexes'.freeze
898
961
  SELECT_VIEWS = 'SELECT * FROM system_schema.views'.freeze
962
+ SELECT_TRIGGERS = 'SELECT * FROM system_schema.triggers'.freeze
899
963
 
900
964
  SELECT_KEYSPACE =
901
965
  'SELECT * FROM system_schema.keyspaces WHERE keyspace_name = ?'.freeze
@@ -913,6 +977,8 @@ module Cassandra
913
977
  'SELECT * FROM system_schema.functions WHERE keyspace_name = ?'.freeze
914
978
  SELECT_KEYSPACE_AGGREGATES =
915
979
  'SELECT * FROM system_schema.aggregates WHERE keyspace_name = ?'.freeze
980
+ SELECT_KEYSPACE_TRIGGERS =
981
+ 'SELECT * FROM system_schema.triggers WHERE keyspace_name = ?'.freeze
916
982
 
917
983
  SELECT_TABLE =
918
984
  'SELECT * ' \
@@ -926,6 +992,10 @@ module Cassandra
926
992
  'SELECT * ' \
927
993
  'FROM system_schema.indexes ' \
928
994
  'WHERE keyspace_name = ? AND table_name = ?'.freeze
995
+ SELECT_TABLE_TRIGGERS =
996
+ 'SELECT * ' \
997
+ 'FROM system_schema.triggers ' \
998
+ 'WHERE keyspace_name = ? AND table_name = ?'.freeze
929
999
 
930
1000
  SELECT_VIEW =
931
1001
  'SELECT * ' \
@@ -984,6 +1054,10 @@ module Cassandra
984
1054
  send_select_request(connection, SELECT_COLUMNS)
985
1055
  end
986
1056
 
1057
+ def select_triggers(connection)
1058
+ send_select_request(connection, SELECT_TRIGGERS)
1059
+ end
1060
+
987
1061
  def select_types(connection)
988
1062
  send_select_request(connection, SELECT_TYPES)
989
1063
  end
@@ -1026,6 +1100,12 @@ module Cassandra
1026
1100
  send_select_request(connection, SELECT_KEYSPACE_VIEWS, params, hints)
1027
1101
  end
1028
1102
 
1103
+ def select_keyspace_triggers(connection, keyspace_name)
1104
+ params = [keyspace_name]
1105
+ hints = [Types.varchar]
1106
+ send_select_request(connection, SELECT_KEYSPACE_TRIGGERS, params, hints)
1107
+ end
1108
+
1029
1109
  def select_keyspace_types(connection, keyspace_name)
1030
1110
  params = [keyspace_name]
1031
1111
  hints = [Types.varchar]
@@ -1071,6 +1151,12 @@ module Cassandra
1071
1151
  send_select_request(connection, SELECT_VIEW, params, hints)
1072
1152
  end
1073
1153
 
1154
+ def select_table_triggers(connection, keyspace_name, table_name)
1155
+ params = [keyspace_name, table_name]
1156
+ hints = [Types.varchar, Types.varchar]
1157
+ send_select_request(connection, SELECT_TABLE_TRIGGERS, params, hints)
1158
+ end
1159
+
1074
1160
  def select_type(connection, keyspace_name, type_name)
1075
1161
  params = [keyspace_name, type_name]
1076
1162
  hints = [Types.varchar, Types.varchar]
@@ -1182,7 +1268,7 @@ module Cassandra
1182
1268
  end
1183
1269
 
1184
1270
  def create_keyspace(keyspace_data, rows_tables, rows_columns, rows_types,
1185
- rows_functions, rows_aggregates, rows_views, rows_indexes)
1271
+ rows_functions, rows_aggregates, rows_views, rows_indexes, rows_triggers)
1186
1272
  keyspace_name = keyspace_data['keyspace_name']
1187
1273
  replication = create_replication(keyspace_data)
1188
1274
 
@@ -1206,10 +1292,11 @@ module Cassandra
1206
1292
 
1207
1293
  lookup_columns = map_rows_by(rows_columns, 'table_name')
1208
1294
  lookup_indexes = map_rows_by(rows_indexes, 'table_name')
1295
+ lookup_triggers = map_rows_by(rows_triggers, 'table_name')
1209
1296
  tables = rows_tables.each_with_object({}) do |row, h|
1210
1297
  table_name = row['table_name']
1211
1298
  h[table_name] = create_table(row, lookup_columns[table_name],
1212
- lookup_indexes[table_name], types)
1299
+ lookup_indexes[table_name], lookup_triggers[table_name], types)
1213
1300
  end
1214
1301
 
1215
1302
  views = rows_views.each_with_object({}) do |row, h|
@@ -1266,7 +1353,8 @@ module Cassandra
1266
1353
  compression,
1267
1354
  is_compact,
1268
1355
  table_data['crc_check_chance'],
1269
- table_data['extensions']
1356
+ table_data['extensions'],
1357
+ table_data['cdc']
1270
1358
  )
1271
1359
  end
1272
1360
 
@@ -1285,7 +1373,7 @@ module Cassandra
1285
1373
  Column.new(name, type, order, is_static, is_frozen)
1286
1374
  end
1287
1375
 
1288
- def create_table(table_data, rows_columns, rows_indexes, types = nil)
1376
+ def create_table(table_data, rows_columns, rows_indexes, rows_triggers, types = nil)
1289
1377
  keyspace_name = table_data['keyspace_name']
1290
1378
  table_name = table_data['table_name']
1291
1379
  table_flags = table_data['flags']
@@ -1352,6 +1440,14 @@ module Cassandra
1352
1440
  rows_indexes.each do |row|
1353
1441
  create_index(table, row)
1354
1442
  end
1443
+
1444
+ # Create Trigger objects and add them to the table.
1445
+ rows_triggers.each do |row_trigger|
1446
+ table.add_trigger(Cassandra::Trigger.new(table,
1447
+ row_trigger['trigger_name'],
1448
+ row_trigger['options']))
1449
+ end
1450
+
1355
1451
  table
1356
1452
  end
1357
1453