cassandra_mocks 0.0.13 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c063a1f6bef33dc9148256cfd940ed22beac02d
4
- data.tar.gz: c21076920e07c9eef84b5fb1bc27dbeae2e3f50a
3
+ metadata.gz: 952c46e902eb98a2c45ff133302d2f867a9e3f06
4
+ data.tar.gz: 80aae79947b0bf4c7c7c6d3d7ecbf6724dc1549f
5
5
  SHA512:
6
- metadata.gz: 34614c002d291f058af84a5391bcfa779e2ede158e390da826feb63ee87bb658805e94d1751953e5b0c651ab74fe6a0384552447ae57e392d729cfb28c4d4e09
7
- data.tar.gz: b07c0efd1a83aaf4e5c1ff8ad01342db29f5dea130d944ae3f94fa4738d86b4cadf7f3146daaefdf5cbffe6e13d2ad0ac1b2a841f608c83dabd5ac88e52b4e8f
6
+ metadata.gz: 4b5bc8c274cbd897c234e41c4ac4ad5bc77d6db745733146b63866ecb77af307e34b490d50e5c45cf39dc500875dc81443444bd4da331ef369207fc3cf9b323b
7
+ data.tar.gz: 5c9411783f168d2228d8c3717166e5179f9ff28188240ee8d347fdbdf7284d8b94a820f410eb386b4fbe710e6904e3396a9e52058ecb957c55b77f03e558636c
@@ -14,11 +14,14 @@
14
14
  # limitations under the License.
15
15
  #++
16
16
 
17
+ require 'concurrent'
17
18
  require 'cassandra'
18
19
  require 'active_support/all'
19
20
  require 'active_support/core_ext/class/attribute_accessors'
20
21
 
21
22
  require 'cassandra_mocks/result_page'
23
+ require 'cassandra_mocks/record'
24
+ require 'cassandra_mocks/row'
22
25
  require 'cassandra_mocks/table'
23
26
  require 'cassandra_mocks/statement/batch'
24
27
  require 'cassandra_mocks/statement/arithmetic'
@@ -6,7 +6,7 @@ module Cassandra
6
6
  def_delegator :@keyspaces, :[], :keyspace
7
7
 
8
8
  def initialize
9
- @keyspaces = {}
9
+ @keyspaces = Concurrent::Map.new
10
10
  end
11
11
 
12
12
  def connect_async(keyspace = nil)
@@ -26,8 +26,11 @@ module Cassandra
26
26
  connect_async(keyspace).get
27
27
  end
28
28
 
29
- def add_keyspace(name)
30
- raise Errors::AlreadyExistsError.new('Cannot create already existing keyspace', 'MockStatement', name, nil) if @keyspaces[name]
29
+ def add_keyspace(name, ignore_existing)
30
+ if @keyspaces[name]
31
+ return if ignore_existing
32
+ raise Errors::AlreadyExistsError.new('Cannot create already existing keyspace', 'MockStatement', name, nil)
33
+ end
31
34
  @keyspaces[name] = Keyspace.new(name)
32
35
  end
33
36
 
@@ -5,11 +5,15 @@ module Cassandra
5
5
  def initialize(name)
6
6
  replication = Replication.new('mock', {})
7
7
  super(name, false, replication, {})
8
+ @tables = Concurrent::Map.new
8
9
  end
9
10
 
10
- def add_table(table_name, primary_key, columns)
11
+ def add_table(table_name, primary_key, columns, ignore_existing)
11
12
  raise Errors::InvalidError.new("Table name '#{table_name}' cannot be greater than 48 characters", 'MockStatement') if table_name.length > 48
12
- raise Errors::AlreadyExistsError.new('Cannot create already existing table', 'MockStatement', nil, table_name) if @tables[table_name]
13
+ if @tables[table_name]
14
+ return if ignore_existing
15
+ raise Errors::AlreadyExistsError.new('Cannot create already existing table', 'MockStatement', nil, table_name)
16
+ end
13
17
 
14
18
  partition_key = primary_key.shift
15
19
  partition_key_columns = partition_key_part(columns, partition_key)
@@ -29,7 +33,7 @@ module Cassandra
29
33
  end
30
34
 
31
35
  def fields(columns, partition_key, primary_key)
32
- columns.except(partition_key + primary_key).map { |name, type| Cassandra::Column.new(name, type, :asc) }
36
+ columns.except(*(partition_key + primary_key)).map { |name, type| Cassandra::Column.new(name, type, :asc) }
33
37
  end
34
38
 
35
39
  end
@@ -0,0 +1,6 @@
1
+ module Cassandra
2
+ module Mocks
3
+ class Record < Struct.new(:values)
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,90 @@
1
+ module Cassandra
2
+ module Mocks
3
+ class Row
4
+ include MonitorMixin
5
+
6
+ attr_reader :clusters, :partition_key
7
+
8
+ def initialize(partition_key)
9
+ @clusters = {}
10
+ @partition_key = partition_key
11
+ super()
12
+ end
13
+
14
+ def insert_record(clustering_columns, record_values, check_exists)
15
+ synchronize do
16
+ record_cluster = record_cluster(clustering_columns[0..-2])
17
+ update_record(check_exists, clustering_columns, record_cluster, record_values)
18
+ end
19
+ end
20
+
21
+ def find_records(clustering_columns)
22
+ cluster = find_cluster(clustering_columns)
23
+ if cluster
24
+ [cluster_values(cluster, [*clustering_columns])].flatten.map(&:values)
25
+ else
26
+ []
27
+ end
28
+ end
29
+
30
+ def delete_records(clustering_columns)
31
+ synchronize do
32
+ if clustering_columns.any?
33
+ cluster = find_cluster(clustering_columns[0..-2])
34
+ cluster.delete(clustering_columns.last) if cluster
35
+ else
36
+ @clusters.clear
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def cluster_values(cluster, values)
44
+ if cluster.is_a?(Record)
45
+ Record.new([*partition_key, *values, *cluster.values])
46
+ else
47
+ cluster.map do |clustering_key, child_cluster|
48
+ cluster_values(child_cluster, values + [clustering_key])
49
+ end
50
+ end
51
+ end
52
+
53
+ def find_cluster(clustering_columns)
54
+ clustering_columns.inject(@clusters) do |cluster, cluster_key|
55
+ cluster[cluster_key] if cluster
56
+ end
57
+ end
58
+
59
+ def record_cluster(partial_clustering_columns)
60
+ partial_clustering_columns.inject(clusters) do |memo, cluster_key|
61
+ memo[cluster_key] ||= {}
62
+ end
63
+ end
64
+
65
+ def update_record(check_exists, clustering_columns, record_cluster, record_values)
66
+ previous_record = record_cluster[clustering_columns.last]
67
+ if previous_record
68
+ update_if_not_exists(check_exists, previous_record, record_values)
69
+ else
70
+ create_record(clustering_columns, record_cluster, record_values)
71
+ end
72
+ end
73
+
74
+ def create_record(clustering_columns, record_cluster, record_values)
75
+ record_cluster[clustering_columns.last] = Record.new(record_values)
76
+ true
77
+ end
78
+
79
+ def update_if_not_exists(check_exists, previous_record, record_values)
80
+ if check_exists
81
+ false
82
+ else
83
+ previous_record.values = record_values
84
+ true
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -25,6 +25,9 @@ module Cassandra
25
25
  end
26
26
 
27
27
  def execute_async(cql, *args)
28
+ options = fetch_options(args)
29
+ args = options.fetch(:arguments) { args }
30
+
28
31
  if cql.is_a?(Cassandra::Statements::Batch)
29
32
  futures = cql.statements.map do |batched_statement|
30
33
  execute_async(batched_statement.statement, *batched_statement.args)
@@ -35,17 +38,18 @@ module Cassandra
35
38
  future = cql.is_a?(Statement) ? Cassandra::Future.value(cql.fill_params(args)) : prepare_async(cql)
36
39
  future.then do |statement|
37
40
  result = ResultPage.new
41
+ # noinspection RubyCaseWithoutElseBlockInspection
38
42
  case statement.action
39
43
  when :create_keyspace
40
- cluster.add_keyspace(statement.args[:keyspace])
44
+ cluster.add_keyspace(statement.args[:keyspace], statement.args[:check_exists])
41
45
  when :create_table
42
- cluster.keyspace(keyspace).add_table(statement.args[:table], statement.args[:primary_key], statement.args[:columns])
46
+ cluster.keyspace(keyspace).add_table(statement.args[:table], statement.args[:primary_key], statement.args[:columns], statement.args[:check_exists])
43
47
  when :insert
44
48
  insert_query(result, statement)
45
49
  when :update
46
50
  update_query(statement)
47
51
  when :truncate
48
- cluster.keyspace(keyspace_for_statement(statement)).table(statement.args[:table]).rows.clear
52
+ cluster.keyspace(keyspace_for_statement(statement)).table(statement.args[:table]).clear
49
53
  when :drop_keyspace
50
54
  cluster.drop_keyspace(statement.args[:keyspace])
51
55
  when :drop_table
@@ -71,9 +75,19 @@ module Cassandra
71
75
 
72
76
  private
73
77
 
78
+ def fetch_options(args)
79
+ if args.last.is_a?(Hash)
80
+ args.pop
81
+ else
82
+ {arguments: args}
83
+ end
84
+ end
85
+
74
86
  def insert_query(result, statement)
75
87
  check_exists = !!statement.args[:check_exists]
76
- inserted = cluster.keyspace(keyspace_for_statement(statement)).table(statement.args[:table]).insert(statement.args[:values], check_exists: check_exists)
88
+ table = cluster.keyspace(keyspace_for_statement(statement)).table(statement.args[:table])
89
+ raise Cassandra::Errors::InvalidError.new('INSERT statement are not allowed on counter tables, use UPDATE instead', 'MockStatement') if table.counter_table?
90
+ inserted = table.insert(statement.args[:values], check_exists: check_exists)
77
91
  result << {'[applied]' => inserted} if check_exists
78
92
  end
79
93
 
@@ -93,15 +107,16 @@ module Cassandra
93
107
  rows_to_update = table.select('*', restriction: statement.args[:filter])
94
108
  rows_to_update = [statement.args[:filter].dup] if rows_to_update.empty?
95
109
  rows_to_update.each do |row|
96
- updated_row = updated_row(row, statement)
110
+ updated_row = updated_row(table, row, statement)
97
111
  cluster.keyspace(keyspace_for_statement(statement)).table(statement.args[:table]).insert(updated_row)
98
112
  end
99
113
  end
100
114
 
101
- def updated_row(row, statement)
115
+ def updated_row(table, row, statement)
102
116
  statement.args[:values].inject(row.dup) do |memo, (column, value)|
103
117
  if value.is_a?(Statement::Arithmetic)
104
- value.apply(memo)
118
+ raise Cassandra::Errors::InvalidError.new("Invalid operation (#{column} = #{column} + ?) for non counter column #{column}", 'MockStatement') unless table.counter_table?
119
+ value.apply!(memo)
105
120
  else
106
121
  memo.merge!(column => value)
107
122
  end
@@ -16,7 +16,7 @@ module Cassandra
16
16
  parse_create_table
17
17
  else
18
18
  @action = :create_keyspace
19
- @args = {keyspace: next_token.value}
19
+ parse_create_keyspace
20
20
  end
21
21
  elsif type_token.truncate?
22
22
  parse_truncate_query
@@ -124,6 +124,16 @@ module Cassandra
124
124
  end
125
125
  end
126
126
 
127
+ def parse_create_keyspace
128
+ keyspace_name_token = next_token
129
+ check_exists = if keyspace_name_token.if?
130
+ next_token
131
+ next_token
132
+ keyspace_name_token = next_token
133
+ end
134
+ @args = {keyspace: keyspace_name_token.value, check_exists: !!check_exists}
135
+ end
136
+
127
137
  def parse_create_table
128
138
  table_name_token = next_token
129
139
  check_exists = if table_name_token.if?
@@ -159,7 +169,7 @@ module Cassandra
159
169
  primary_key = [partition_key, *primary_key_parts]
160
170
  end
161
171
 
162
- @args = {table: table_name, check_exists: !!check_exists, columns: additional_columns.merge({column_name => column_type}), primary_key: primary_key}
172
+ @args = {table: table_name, check_exists: !!check_exists, columns: additional_columns.merge!({column_name => column_type}), primary_key: primary_key}
163
173
  end
164
174
 
165
175
  def parse_truncate_query
@@ -3,8 +3,8 @@ module Cassandra
3
3
  class Statement
4
4
  class Arithmetic < Struct.new(:operation, :column, :amount)
5
5
 
6
- def apply(row)
7
- row.merge(column => (row[column] || 0).public_send(operator, amount))
6
+ def apply!(row)
7
+ row.merge!(column => (row[column] || 0).public_send(operator, amount))
8
8
  end
9
9
 
10
10
  private
@@ -1,42 +1,96 @@
1
1
  module Cassandra
2
2
  module Mocks
3
3
  class Table < Cassandra::Table
4
+ extend Forwardable
5
+
6
+ def_delegator :@rows, :clear
7
+
4
8
  def initialize(keyspace, name, partition_key, clustering_key, fields)
9
+ @rows = Concurrent::Map.new { |hash, key| hash[key] = Row.new(key) }
10
+
5
11
  compaction = Cassandra::Table::Compaction.new('mock', {})
6
12
  options = Cassandra::Table::Options.new({}, compaction, {}, false, 'mock')
7
13
  column_map = column_map(partition_key, clustering_key, fields)
14
+
15
+ @counter_column = fields.find { |field| field.type.to_sym == :counter }
16
+ has_non_counters = !!fields.find { |field| field.type.to_sym != :counter }
17
+
18
+ if counter_column && has_non_counters
19
+ raise Cassandra::Errors::ConfigurationError.new("Cannot add counter column '#{counter_column.name}' to non-counter column family", 'MockStatement')
20
+ end
21
+
8
22
  super(keyspace, name, partition_key, clustering_key, column_map, options, [])
23
+ @column_map = columns.inject({}) do |memo, column|
24
+ memo.merge!(column.name => column)
25
+ end
26
+ @partition_key_set = Set.new(partition_key_names)
27
+ end
28
+
29
+ def rows
30
+ results = []
31
+ @rows.each_pair do |_, row|
32
+ row_results = record_attributes(row.find_records([]))
33
+ results << row_results
34
+ end
35
+ results.flatten
36
+ end
37
+
38
+ def counter_table?
39
+ !!counter_column
9
40
  end
10
41
 
11
42
  def insert(attributes, options = {})
12
43
  validate_columns!(attributes)
13
44
  validate_primary_key_presence!(attributes)
14
45
 
15
- prev_row_index = rows.find_index do |row|
16
- row.slice(*primary_key_names) == attributes.slice(*primary_key_names)
17
- end
18
-
19
- if prev_row_index
20
- return false if options[:check_exists]
21
- rows[prev_row_index] = attributes
22
- else
23
- rows << attributes
24
- end
25
- true
46
+ row = @rows[attribute_partition_key(attributes)]
47
+ row.insert_record(attribute_clustering_key(attributes), attribute_fields(attributes), options[:check_exists])
26
48
  end
27
49
 
28
50
  def select(*columns)
29
51
  filter = select_filter(columns)
30
52
  limit = filter.delete(:limit)
31
53
  order = select_order(filter)
32
- filter = filter.fetch(:restriction) { {} }
33
- unless filter.empty?
34
- validate_partion_key_filter!(filter)
35
- validate_clustering_column_filter!(filter)
36
- raise_if_fields_restricted!(filter)
54
+
55
+ order_keys_in_partition = order.keys.select { |column| partition_key_names.include?(column) }
56
+ if order_keys_in_partition.any?
57
+ raise Cassandra::Errors::InvalidError.new("Order by is currently only supported on the clustered columns of the PRIMARY KEY, got #{order_keys_in_partition * ', '}", 'MockStatement')
58
+ end
59
+
60
+ missing_ordering_keys = order.keys.select { |column| !column_names.include?(column) }
61
+ if missing_ordering_keys.any?
62
+ raise Cassandra::Errors::InvalidError.new("Order by on unknown column(s) #{missing_ordering_keys * ', '}", 'MockStatement')
63
+ end
64
+
65
+ out_of_order = order.keys.each.with_index.any? { |column, index| clustering_key_names[index] != column }
66
+ if out_of_order
67
+ raise Cassandra::Errors::InvalidError.new("Order by currently only support the ordering of columns following their declared order in the PRIMARY KEY (expected #{clustering_key_names * ', '} got #{order.keys * ', '})", 'MockStatement')
68
+ end
69
+
70
+ inconsistent_order = (order.values.uniq.count > 1)
71
+ if inconsistent_order
72
+ raise Cassandra::Errors::InvalidError.new('Ordering direction must be consistent across all clustering columns', 'MockStatement')
37
73
  end
38
74
 
39
- filtered_rows = filtered_rows(filter)
75
+ filter = filter.fetch(:restriction) { {} }
76
+ validate_filter!(filter)
77
+
78
+ filtered_rows = if filter.any?
79
+ partition_key = attribute_partition_key(filter)
80
+ partition_range = (partition_key.pop if partition_key.last.is_a?(Array))
81
+ cluster_filter = filter.except(*partition_key_names)
82
+ cluster_key = attribute_partial_clustering_key(cluster_filter)
83
+ _, cluster_slice = cluster_filter.find do |_, value|
84
+ restriction_is_slice?(value)
85
+ end
86
+
87
+ records = partially_filtered_rows(partition_range, partition_key, cluster_key)
88
+ rows = record_attributes(records)
89
+ filtered_rows(cluster_slice, rows)
90
+ else
91
+ self.rows
92
+ end
93
+
40
94
  sorted_rows = filtered_rows.sort do |lhs, rhs|
41
95
  compare_rows(0, lhs, rhs, order)
42
96
  end
@@ -50,12 +104,41 @@ module Cassandra
50
104
  end
51
105
 
52
106
  def delete(filter)
53
- rows_to_remove = select('*', restriction: filter)
54
- @rows.reject! { |row| rows_to_remove.include?(row) }
107
+ validate_filter!(filter)
108
+ row = @rows[attribute_partition_key(filter)]
109
+ row.delete_records(attribute_partial_clustering_key(filter))
55
110
  end
56
111
 
57
- def rows
58
- @rows ||= []
112
+ def attribute_partition_key(attributes)
113
+ partition_key_names.map { |column| attributes[column] }
114
+ end
115
+
116
+ def attribute_clustering_key(attributes)
117
+ clustering_key_names.map do |column|
118
+ value = attributes[column]
119
+ value unless restriction_is_slice?(value)
120
+ end
121
+ end
122
+
123
+ def attribute_partial_clustering_key(attributes)
124
+ attribute_clustering_key(attributes).compact
125
+ end
126
+
127
+ def attribute_fields(attributes)
128
+ field_names.map { |column| attributes[column] }
129
+ end
130
+
131
+ def restriction_is_slice?(value)
132
+ value.is_a?(Statement::Comparitor) || value.is_a?(Array)
133
+ end
134
+
135
+ def validate_filter!(filter)
136
+ unless filter.empty?
137
+ validate_range_query!(filter)
138
+ validate_partition_key_filter!(filter)
139
+ validate_clustering_column_filter!(filter)
140
+ raise_if_fields_restricted!(filter)
141
+ end
59
142
  end
60
143
 
61
144
  # make #partition_key public
@@ -70,8 +153,11 @@ module Cassandra
70
153
 
71
154
  private
72
155
 
156
+ attr_reader :counter_column
157
+ def_delegator :@column_map, :[], :find_column
158
+
73
159
  def select_filter(columns)
74
- columns.last.is_a?(Hash) ? columns.pop : {}
160
+ columns.last.is_a?(Hash) ? columns.pop.dup : {}
75
161
  end
76
162
 
77
163
  def select_order(filter)
@@ -145,42 +231,15 @@ module Cassandra
145
231
  filter[column]
146
232
  end
147
233
 
148
- def filtered_rows(filter)
149
- filter ? apply_filter(filter) : rows
150
- end
151
-
152
- def apply_filter(filter)
153
- rows.select do |row|
154
- partial_row = filter_slices_row(filter, row)
155
- filter.all? do |column, value|
156
- if value.is_a?(Statement::Comparitor)
157
- value.check_against(partial_row)
158
- elsif value.is_a?(Array)
159
- if value.first.is_a?(Statement::Comparitor)
160
- value.all? { |value| value.check_against(partial_row) }
161
- else
162
- value.include?(partial_row[column])
163
- end
164
- else
165
- partial_row[column] == value
166
- end
167
- end
168
- end
169
- end
170
-
171
- def filter_slices_row(filter, row)
172
- filter.keys.inject({}) do |memo, key, _|
173
- value = if key.is_a?(Array)
174
- row.values_at(*key)
175
- else
176
- row[key]
177
- end
178
- memo.merge!(key => value)
234
+ def validate_range_query!(filter)
235
+ invalid_partition_range_column = partition_key_names[0..-2].find { |column| filter[column].is_a?(Array) }
236
+ if invalid_partition_range_column
237
+ raise Cassandra::Errors::InvalidError.new("Partition KEY part #{invalid_partition_range_column} cannot be restricted by IN relation (only the last part of the partition key can)", 'MockStatement')
179
238
  end
180
239
  end
181
240
 
182
- def validate_partion_key_filter!(filter)
183
- missing_partition_keys = Set.new(partition_key_names) - filter.keys
241
+ def validate_partition_key_filter!(filter)
242
+ missing_partition_keys = @partition_key_set - filter.keys
184
243
  raise Cassandra::Errors::InvalidError.new("Missing partition key part(s) #{missing_partition_keys.map(&:inspect) * ', '}", 'MockStatement') unless missing_partition_keys.empty?
185
244
  end
186
245
 
@@ -203,6 +262,61 @@ module Cassandra
203
262
  row[primary_key_names[primary_key_index]]
204
263
  end
205
264
 
265
+ def record_attributes(records)
266
+ records.map do |record|
267
+ attributes = {}
268
+ column_names.each.with_index do |column, index|
269
+ attributes[column] = record[index]
270
+ end
271
+ attributes
272
+ end
273
+ end
274
+
275
+ def partially_filtered_rows(partition_range, partition_key, cluster_key)
276
+ if partition_range
277
+ partition_range_records(partition_range, partition_key, cluster_key)
278
+ else
279
+ records_for_row(partition_key, cluster_key)
280
+ end
281
+ end
282
+
283
+ def partition_range_records(partition_range, partition_key, cluster_key)
284
+ partition_range.map do |part|
285
+ records_for_row(partition_key + [part], cluster_key)
286
+ end.flatten(1)
287
+ end
288
+
289
+ def records_for_row(partition_key, cluster_key)
290
+ row = @rows[partition_key]
291
+ row.find_records(cluster_key)
292
+ end
293
+
294
+ def filtered_rows(cluster_slice, rows)
295
+ cluster_slice ? apply_filter(cluster_slice, rows) : rows
296
+ end
297
+
298
+ def apply_filter(cluster_slice, rows)
299
+ rows.select do |row|
300
+ partial_row = partial_row(cluster_slice, row)
301
+
302
+ if cluster_slice.is_a?(Statement::Comparitor)
303
+ cluster_slice.check_against(partial_row)
304
+ elsif cluster_slice.is_a?(Array)
305
+ cluster_slice.all? { |value| value.check_against(partial_row) }
306
+ end
307
+ end
308
+ end
309
+
310
+ def partial_row(cluster_slice, row)
311
+ comparitor = cluster_slice.is_a?(Statement::Comparitor) ? cluster_slice : cluster_slice.first
312
+ value = if comparitor.column.is_a?(Array)
313
+ row.values_at(*comparitor.column)
314
+ else
315
+ row[comparitor.column]
316
+ end
317
+ {comparitor.column => value}
318
+ end
319
+
206
320
  def primary_key_names
207
321
  partition_key_names + clustering_key_names
208
322
  end
@@ -219,8 +333,8 @@ module Cassandra
219
333
  columns.map(&:name)
220
334
  end
221
335
 
222
- def find_column(name)
223
- columns.find { |column| column.name == name }
336
+ def field_names
337
+ column_names - (partition_key_names + clustering_key_names)
224
338
  end
225
339
 
226
340
  def column_map(partition_key, clustering_key, fields)
metadata CHANGED
@@ -1,29 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra_mocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas RM Rogers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-14 00:00:00.000000000 Z
11
+ date: 2016-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-driver
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.1'
20
+ - - <=
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.1
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - ~>
27
+ - - '>='
25
28
  - !ruby/object:Gem::Version
26
29
  version: '1.1'
30
+ - - <=
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: concurrent-ruby
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: 1.0.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.0
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: activesupport
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +72,9 @@ files:
52
72
  - lib/cassandra_mocks.rb
53
73
  - lib/cassandra_mocks/cluster.rb
54
74
  - lib/cassandra_mocks/keyspace.rb
75
+ - lib/cassandra_mocks/record.rb
55
76
  - lib/cassandra_mocks/result_page.rb
77
+ - lib/cassandra_mocks/row.rb
56
78
  - lib/cassandra_mocks/session.rb
57
79
  - lib/cassandra_mocks/statement.rb
58
80
  - lib/cassandra_mocks/statement/arithmetic.rb