cassandra_mocks 0.0.13 → 1.0.8

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.
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