cequel 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +8 -0
  5. data/lib/cequel/errors.rb +2 -0
  6. data/lib/cequel/metal/new_relic_instrumentation.rb +2 -1
  7. data/lib/cequel/record.rb +8 -0
  8. data/lib/cequel/record/schema.rb +30 -23
  9. data/lib/cequel/schema.rb +3 -2
  10. data/lib/cequel/schema/column.rb +11 -1
  11. data/lib/cequel/schema/keyspace.rb +18 -7
  12. data/lib/cequel/schema/patch.rb +152 -0
  13. data/lib/cequel/schema/table.rb +55 -137
  14. data/lib/cequel/schema/table_desc_dsl.rb +196 -0
  15. data/lib/cequel/schema/table_differ.rb +112 -0
  16. data/lib/cequel/schema/table_property.rb +14 -0
  17. data/lib/cequel/schema/table_reader.rb +81 -85
  18. data/lib/cequel/schema/table_updater.rb +0 -17
  19. data/lib/cequel/schema/table_writer.rb +10 -9
  20. data/lib/cequel/version.rb +1 -1
  21. data/spec/examples/metal/data_set_spec.rb +156 -153
  22. data/spec/examples/metal/keyspace_spec.rb +4 -4
  23. data/spec/examples/record/associations_spec.rb +6 -0
  24. data/spec/examples/record/mass_assignment_spec.rb +2 -2
  25. data/spec/examples/record/properties_spec.rb +1 -0
  26. data/spec/examples/record/record_set_spec.rb +1 -1
  27. data/spec/examples/schema/patch_spec.rb +190 -0
  28. data/spec/examples/schema/table_differ_spec.rb +280 -0
  29. data/spec/examples/schema/table_reader_spec.rb +379 -354
  30. data/spec/examples/schema/table_updater_spec.rb +0 -12
  31. data/spec/examples/spec_helper.rb +5 -5
  32. data/spec/examples/spec_support/preparation_spec.rb +4 -0
  33. data/spec/support/helpers.rb +23 -0
  34. metadata +9 -6
  35. data/lib/cequel/schema/create_table_dsl.rb +0 -88
  36. data/lib/cequel/schema/table_synchronizer.rb +0 -180
  37. data/spec/examples/schema/table_synchronizer_spec.rb +0 -200
@@ -8,63 +8,77 @@ describe Cequel::Schema::TableReader do
8
8
  cequel.schema.drop_table(table_name)
9
9
  end
10
10
 
11
- let(:table) { cequel.schema.read_table(table_name) }
12
-
13
- describe 'reading simple key' do
11
+ describe ".read(keyspace, table_name)" do
14
12
  before do
15
13
  cequel.execute("CREATE TABLE #{table_name} (permalink text PRIMARY KEY)")
16
14
  cequel.send(:cluster).refresh_schema
17
15
  end
18
16
 
19
- it 'should read name correctly' do
20
- expect(table.partition_key_columns.first.name).to eq(:permalink)
17
+ it "returns a table" do
18
+ expect(
19
+ described_class.read(cequel, table_name)
20
+ ).to be_kind_of Cequel::Schema::Table
21
21
  end
22
+ end
22
23
 
23
- it 'should read type correctly' do
24
- expect(table.partition_key_columns.first.type).to be_a(Cequel::Type::Text)
25
- end
24
+ describe "#call" do
25
+ let(:table) { described_class.new(fetch_table_data).call }
26
26
 
27
- it 'should have no nonpartition keys' do
28
- expect(table.clustering_columns).to be_empty
29
- end
30
- end # describe 'reading simple key'
27
+ context 'simple key' do
28
+ before do
29
+ cequel.execute("CREATE TABLE #{table_name} (permalink text PRIMARY KEY)")
30
+ cequel.send(:cluster).refresh_schema
31
+ end
31
32
 
32
- describe 'reading single non-partition key' do
33
- before do
34
- cequel.execute <<-CQL
33
+ it 'should read name correctly' do
34
+ expect(table.partition_key_columns.first.name).to eq(:permalink)
35
+ end
36
+
37
+ it 'should read type correctly' do
38
+ expect(table.partition_key_columns.first.type).to be_a(Cequel::Type::Text)
39
+ end
40
+
41
+ it 'should have no nonpartition keys' do
42
+ expect(table.clustering_columns).to be_empty
43
+ end
44
+ end # context 'simple key'
45
+
46
+ context 'single cluster key' do
47
+ before do
48
+ cequel.execute <<-CQL
35
49
  CREATE TABLE #{table_name} (
36
50
  blog_subdomain text,
37
51
  permalink ascii,
38
52
  PRIMARY KEY (blog_subdomain, permalink)
39
53
  )
40
54
  CQL
41
- end
55
+ end
42
56
 
43
- it 'should read partition key name' do
44
- expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain])
45
- end
57
+ it 'should read partition key name' do
58
+ expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain])
59
+ end
46
60
 
47
- it 'should read partition key type' do
48
- expect(table.partition_key_columns.map(&:type)).to eq([Cequel::Type::Text.instance])
49
- end
61
+ it 'should read partition key type' do
62
+ expect(table.partition_key_columns.map(&:type)).to eq([Cequel::Type::Text.instance])
63
+ end
50
64
 
51
- it 'should read non-partition key name' do
52
- expect(table.clustering_columns.map(&:name)).to eq([:permalink])
53
- end
65
+ it 'should read non-partition key name' do
66
+ expect(table.clustering_columns.map(&:name)).to eq([:permalink])
67
+ end
54
68
 
55
- it 'should read non-partition key type' do
56
- expect(table.clustering_columns.map(&:type)).
57
- to eq([Cequel::Type::Ascii.instance])
58
- end
69
+ it 'should read non-partition key type' do
70
+ expect(table.clustering_columns.map(&:type)).
71
+ to eq([Cequel::Type::Ascii.instance])
72
+ end
59
73
 
60
- it 'should default clustering order to asc' do
61
- expect(table.clustering_columns.map(&:clustering_order)).to eq([:asc])
62
- end
63
- end # describe 'reading single non-partition key'
74
+ it 'should default clustering order to asc' do
75
+ expect(table.clustering_columns.map(&:clustering_order)).to eq([:asc])
76
+ end
77
+ end # context 'single cluster key'
64
78
 
65
- describe 'reading reverse-ordered non-partition key' do
66
- before do
67
- cequel.execute <<-CQL
79
+ context 'reverse-ordered cluster key' do
80
+ before do
81
+ cequel.execute <<-CQL
68
82
  CREATE TABLE #{table_name} (
69
83
  blog_subdomain text,
70
84
  permalink ascii,
@@ -72,25 +86,25 @@ describe Cequel::Schema::TableReader do
72
86
  )
73
87
  WITH CLUSTERING ORDER BY (permalink DESC)
74
88
  CQL
75
- end
89
+ end
76
90
 
77
- it 'should read non-partition key name' do
78
- expect(table.clustering_columns.map(&:name)).to eq([:permalink])
79
- end
91
+ it 'should read non-partition key name' do
92
+ expect(table.clustering_columns.map(&:name)).to eq([:permalink])
93
+ end
80
94
 
81
- it 'should read non-partition key type' do
82
- expect(table.clustering_columns.map(&:type)).
83
- to eq([Cequel::Type::Ascii.instance])
84
- end
95
+ it 'should read non-partition key type' do
96
+ expect(table.clustering_columns.map(&:type)).
97
+ to eq([Cequel::Type::Ascii.instance])
98
+ end
85
99
 
86
- it 'should recognize reversed clustering order' do
87
- expect(table.clustering_columns.map(&:clustering_order)).to eq([:desc])
88
- end
89
- end # describe 'reading reverse-ordered non-partition key'
100
+ it 'should recognize reversed clustering order' do
101
+ expect(table.clustering_columns.map(&:clustering_order)).to eq([:desc])
102
+ end
103
+ end # context 'reverse-ordered cluster key'
90
104
 
91
- describe 'reading compound non-partition key' do
92
- before do
93
- cequel.execute <<-CQL
105
+ context 'compound cluster key' do
106
+ before do
107
+ cequel.execute <<-CQL
94
108
  CREATE TABLE #{table_name} (
95
109
  blog_subdomain text,
96
110
  permalink ascii,
@@ -99,51 +113,51 @@ describe Cequel::Schema::TableReader do
99
113
  )
100
114
  WITH CLUSTERING ORDER BY (permalink DESC, author_id ASC)
101
115
  CQL
102
- end
116
+ end
103
117
 
104
- it 'should read non-partition key names' do
105
- expect(table.clustering_columns.map(&:name)).to eq([:permalink, :author_id])
106
- end
118
+ it 'should read non-partition key names' do
119
+ expect(table.clustering_columns.map(&:name)).to eq([:permalink, :author_id])
120
+ end
107
121
 
108
- it 'should read non-partition key types' do
109
- expect(table.clustering_columns.map(&:type)).
110
- to eq([Cequel::Type::Ascii.instance, Cequel::Type::Uuid.instance])
111
- end
122
+ it 'should read non-partition key types' do
123
+ expect(table.clustering_columns.map(&:type)).
124
+ to eq([Cequel::Type::Ascii.instance, Cequel::Type::Uuid.instance])
125
+ end
112
126
 
113
- it 'should read heterogeneous clustering orders' do
114
- expect(table.clustering_columns.map(&:clustering_order)).to eq([:desc, :asc])
115
- end
116
- end # describe 'reading compound non-partition key'
127
+ it 'should read heterogeneous clustering orders' do
128
+ expect(table.clustering_columns.map(&:clustering_order)).to eq([:desc, :asc])
129
+ end
130
+ end # context 'compound context key'
117
131
 
118
- describe 'reading compound partition key' do
119
- before do
120
- cequel.execute <<-CQL
132
+ context 'compound partition key' do
133
+ before do
134
+ cequel.execute <<-CQL
121
135
  CREATE TABLE #{table_name} (
122
136
  blog_subdomain text,
123
137
  permalink ascii,
124
138
  PRIMARY KEY ((blog_subdomain, permalink))
125
139
  )
126
140
  CQL
127
- end
141
+ end
128
142
 
129
- it 'should read partition key names' do
130
- expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain, :permalink])
131
- end
143
+ it 'should read partition key names' do
144
+ expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain, :permalink])
145
+ end
132
146
 
133
- it 'should read partition key types' do
134
- expect(table.partition_key_columns.map(&:type)).
135
- to eq([Cequel::Type::Text.instance, Cequel::Type::Ascii.instance])
136
- end
147
+ it 'should read partition key types' do
148
+ expect(table.partition_key_columns.map(&:type)).
149
+ to eq([Cequel::Type::Text.instance, Cequel::Type::Ascii.instance])
150
+ end
137
151
 
138
- it 'should have empty nonpartition keys' do
139
- expect(table.clustering_columns).to be_empty
140
- end
152
+ it 'should have empty nonpartition keys' do
153
+ expect(table.clustering_columns).to be_empty
154
+ end
141
155
 
142
- end # describe 'reading compound partition key'
156
+ end # context 'compound partition key'
143
157
 
144
- describe 'reading compound partition and non-partition keys' do
145
- before do
146
- cequel.execute <<-CQL
158
+ context 'compound partition and cluster keys' do
159
+ before do
160
+ cequel.execute <<-CQL
147
161
  CREATE TABLE #{table_name} (
148
162
  blog_subdomain text,
149
163
  permalink ascii,
@@ -153,283 +167,294 @@ describe Cequel::Schema::TableReader do
153
167
  )
154
168
  WITH CLUSTERING ORDER BY (author_id ASC, published_at DESC)
155
169
  CQL
170
+ end
171
+
172
+ it 'should read partition key names' do
173
+ expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain, :permalink])
174
+ end
175
+
176
+ it 'should read partition key types' do
177
+ expect(table.partition_key_columns.map(&:type)).
178
+ to eq([Cequel::Type::Text.instance, Cequel::Type::Ascii.instance])
179
+ end
180
+
181
+ it 'should read non-partition key names' do
182
+ expect(table.clustering_columns.map(&:name)).
183
+ to eq([:author_id, :published_at])
184
+ end
185
+
186
+ it 'should read non-partition key types' do
187
+ expect(table.clustering_columns.map(&:type)).to eq(
188
+ [Cequel::Type::Uuid.instance, Cequel::Type::Timestamp.instance]
189
+ )
190
+ end
191
+
192
+ it 'should read clustering order' do
193
+ expect(table.clustering_columns.map(&:clustering_order)).to eq([:asc, :desc])
194
+ end
195
+
196
+ end # context 'compound partition and context keys'
197
+
198
+ context 'data columns' do
199
+
200
+ before do
201
+ cequel.execute <<-CQL
202
+ CREATE TABLE #{table_name} (
203
+ blog_subdomain text,
204
+ permalink ascii,
205
+ title text,
206
+ author_id uuid,
207
+ categories LIST <text>,
208
+ tags SET <text>,
209
+ trackbacks MAP <timestamp,ascii>,
210
+ PRIMARY KEY (blog_subdomain, permalink)
211
+ )
212
+ CQL
213
+ cequel.execute("CREATE INDEX posts_author_id_idx ON #{table_name} (author_id)")
214
+ end
215
+
216
+ it 'should read types of scalar data columns' do
217
+ expect(table.data_columns.find { |column| column.name == :title }.type).
218
+ to eq(Cequel::Type[:text])
219
+ expect(table.data_columns.find { |column| column.name == :author_id }.type).
220
+ to eq(Cequel::Type[:uuid])
221
+ end
222
+
223
+ it 'should read index attributes' do
224
+ expect(table.data_columns.find { |column| column.name == :author_id }.index_name).
225
+ to eq(:posts_author_id_idx)
226
+ end
227
+
228
+ it 'should leave nil index for non-indexed columns' do
229
+ expect(table.data_columns.find { |column| column.name == :title }.index_name).
230
+ to be_nil
231
+ end
232
+
233
+ it 'should read list columns' do
234
+ expect(table.data_columns.find { |column| column.name == :categories }).
235
+ to be_a(Cequel::Schema::List)
236
+ end
237
+
238
+ it 'should read list column type' do
239
+ expect(table.data_columns.find { |column| column.name == :categories }.type).
240
+ to eq(Cequel::Type[:text])
241
+ end
242
+
243
+ it 'should read set columns' do
244
+ expect(table.data_columns.find { |column| column.name == :tags }).
245
+ to be_a(Cequel::Schema::Set)
246
+ end
247
+
248
+ it 'should read set column type' do
249
+ expect(table.data_columns.find { |column| column.name == :tags }.type).
250
+ to eq(Cequel::Type[:text])
251
+ end
252
+
253
+ it 'should read map columns' do
254
+ expect(table.data_columns.find { |column| column.name == :trackbacks }).
255
+ to be_a(Cequel::Schema::Map)
256
+ end
257
+
258
+ it 'should read map column key type' do
259
+ expect(table.data_columns.find { |column| column.name == :trackbacks }.key_type).
260
+ to eq(Cequel::Type[:timestamp])
261
+ end
262
+
263
+ it 'should read map column value type' do
264
+ expect(table.data_columns.find { |column| column.name == :trackbacks }.
265
+ value_type).to eq(Cequel::Type[:ascii])
266
+ end
267
+
268
+ end # context 'data columns'
269
+
270
+ context 'storage properties' do
271
+
272
+ before do
273
+ cequel.execute <<-CQL
274
+ CREATE TABLE #{table_name} (permalink text PRIMARY KEY)
275
+ WITH bloom_filter_fp_chance = 0.02
276
+ AND comment = 'Posts table'
277
+ AND compaction = {
278
+ 'class' : 'SizeTieredCompactionStrategy',
279
+ 'bucket_high' : 1.8,
280
+ 'max_threshold' : 64,
281
+ 'min_sstable_size' : 50,
282
+ 'tombstone_compaction_interval' : 2
283
+ } AND compression = {
284
+ 'sstable_compression' : 'DeflateCompressor',
285
+ 'chunk_length_kb' : 128,
286
+ 'crc_check_chance' : 0.5
287
+ }
288
+ CQL
289
+ end
290
+
291
+ it 'should read float properties' do
292
+ expect(table.property(:bloom_filter_fp_chance)).to eq(0.02)
293
+ end
294
+
295
+ it 'should read string properties' do
296
+ expect(table.property(:comment)).to eq('Posts table')
297
+ end
298
+
299
+ it 'should read and simplify compaction class' do
300
+ expect(table.property(:compaction)[:class]).
301
+ to eq('SizeTieredCompactionStrategy')
302
+ end
303
+
304
+ it 'should read float properties from compaction hash' do
305
+ expect(table.property(:compaction)[:bucket_high]).to eq(1.8)
306
+ end
307
+
308
+ it 'should read integer properties from compaction hash' do
309
+ expect(table.property(:compaction)[:max_threshold]).to eq(64)
310
+ end
311
+
312
+ it 'should read and simplify compression class' do
313
+ expect(table.property(:compression)[:sstable_compression] ||
314
+ table.property(:compression)[:class]).
315
+ to eq('DeflateCompressor')
316
+ end
317
+
318
+ it 'should read integer properties from compression class' do
319
+ expect(table.property(:compression)[:chunk_length_kb]).to eq(128)
320
+ end
321
+
322
+ it 'should read float properties from compression class' do
323
+ expect(table.property(:compression)[:crc_check_chance]).to eq(0.5)
324
+ end
325
+
326
+ it 'should recognize no compact storage' do
327
+ expect(table).not_to be_compact_storage
328
+ end
329
+ end # context 'storage properties'
330
+
331
+ context 'skinny-row compact storage' do
332
+ before do
333
+ cequel.execute <<-CQL
334
+ CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
335
+ WITH COMPACT STORAGE
336
+ CQL
337
+ end
338
+ subject { table }
339
+
340
+ it { is_expected.to be_compact_storage }
341
+ its(:partition_key_columns) { should ==
342
+ [Cequel::Schema::PartitionKey.new(:permalink, :text)] }
343
+ its(:clustering_columns) { should be_empty }
344
+ specify { expect(table.data_columns).to contain_exactly(
345
+ Cequel::Schema::DataColumn.new(:title, :text),
346
+ Cequel::Schema::DataColumn.new(:body, :text)) }
347
+ end
348
+
349
+ context 'wide-row compact storage' do
350
+ before do
351
+ cequel.execute <<-CQL
352
+ CREATE TABLE #{table_name} (
353
+ blog_subdomain text,
354
+ id uuid,
355
+ data text,
356
+ PRIMARY KEY (blog_subdomain, id)
357
+ )
358
+ WITH COMPACT STORAGE
359
+ CQL
360
+ end
361
+ subject { table }
362
+
363
+ it { is_expected.to be_compact_storage }
364
+ its(:partition_key_columns) { should ==
365
+ [Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)] }
366
+ its(:clustering_columns) { should ==
367
+ [Cequel::Schema::ClusteringColumn.new(:id, :uuid)] }
368
+ its(:data_columns) { should ==
369
+ [Cequel::Schema::DataColumn.new(:data, :text)] }
370
+ end
371
+
372
+ context 'materialized view exists', cql: '~> 3.4' do
373
+ let!(:name) { table_name }
374
+ let(:view_name) { "#{name}_view" }
375
+ before do
376
+ cequel.execute <<-CQL
377
+ CREATE TABLE #{table_name} (
378
+ blog_subdomain text,
379
+ permalink ascii,
380
+ PRIMARY KEY (blog_subdomain, permalink)
381
+ )
382
+ CQL
383
+ cequel.execute <<-CQL
384
+ CREATE MATERIALIZED VIEW #{view_name} AS
385
+ SELECT blog_subdomain, permalink
386
+ FROM #{name}
387
+ WHERE blog_subdomain IS NOT NULL AND permalink IS NOT NULL
388
+ PRIMARY KEY ( blog_subdomain, permalink )
389
+ CQL
390
+ end
391
+ after do
392
+ cequel.schema.drop_materialized_view(view_name)
393
+ end
394
+
395
+ let(:view) { described_class.new(fetch_view_data).call }
396
+
397
+ it "recognizes that regular tables are not views" do
398
+ expect( table.materialized_view? ).to be false
399
+ end
400
+
401
+ it "recognizes thats view tables are views" do
402
+ expect( view.materialized_view? ).to be true
403
+ end
404
+ end
405
+
406
+ context 'skinny-row legacy table', thrift: true do
407
+ before do
408
+ legacy_connection.execute <<-CQL
409
+ CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
410
+ CQL
411
+ end
412
+ subject { table }
413
+
414
+ it { is_expected.to be_compact_storage }
415
+ its(:partition_key_columns) { is_expected.to eq(
416
+ [Cequel::Schema::PartitionKey.new(:permalink, :text)]
417
+ ) }
418
+ its(:clustering_columns) { is_expected.to be_empty }
419
+ its(:data_columns) { is_expected.to match_array(
420
+ [Cequel::Schema::DataColumn.new(:title, :text),
421
+ Cequel::Schema::DataColumn.new(:body, :text)]
422
+ ) }
423
+ end
424
+
425
+ context 'wide-row legacy table', thrift: true do
426
+ before do
427
+ legacy_connection.execute(<<-CQL2)
428
+ CREATE COLUMNFAMILY #{table_name} (blog_subdomain text PRIMARY KEY)
429
+ WITH comparator=uuid AND default_validation=text
430
+ CQL2
431
+ end
432
+ subject { table }
433
+
434
+ it { is_expected.to be_compact_storage }
435
+ its(:partition_key_columns) { is_expected.to eq(
436
+ [Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)]
437
+ ) }
438
+ its(:clustering_columns) { is_expected.to eq(
439
+ [Cequel::Schema::ClusteringColumn.new(:column1, :uuid)]
440
+ ) }
441
+ its(:data_columns) { is_expected.to eq(
442
+ [Cequel::Schema::DataColumn.new(:value, :text)]
443
+ ) }
156
444
  end
157
-
158
- it 'should read partition key names' do
159
- expect(table.partition_key_columns.map(&:name)).to eq([:blog_subdomain, :permalink])
160
- end
161
-
162
- it 'should read partition key types' do
163
- expect(table.partition_key_columns.map(&:type)).
164
- to eq([Cequel::Type::Text.instance, Cequel::Type::Ascii.instance])
165
- end
166
-
167
- it 'should read non-partition key names' do
168
- expect(table.clustering_columns.map(&:name)).
169
- to eq([:author_id, :published_at])
170
- end
171
-
172
- it 'should read non-partition key types' do
173
- expect(table.clustering_columns.map(&:type)).to eq(
174
- [Cequel::Type::Uuid.instance, Cequel::Type::Timestamp.instance]
175
- )
176
- end
177
-
178
- it 'should read clustering order' do
179
- expect(table.clustering_columns.map(&:clustering_order)).to eq([:asc, :desc])
180
- end
181
-
182
- end # describe 'reading compound partition and non-partition keys'
183
-
184
- describe 'reading data columns' do
185
-
186
- before do
187
- cequel.execute <<-CQL
188
- CREATE TABLE #{table_name} (
189
- blog_subdomain text,
190
- permalink ascii,
191
- title text,
192
- author_id uuid,
193
- categories LIST <text>,
194
- tags SET <text>,
195
- trackbacks MAP <timestamp,ascii>,
196
- PRIMARY KEY (blog_subdomain, permalink)
197
- )
198
- CQL
199
- cequel.execute("CREATE INDEX posts_author_id_idx ON #{table_name} (author_id)")
200
- end
201
-
202
- it 'should read types of scalar data columns' do
203
- expect(table.data_columns.find { |column| column.name == :title }.type).
204
- to eq(Cequel::Type[:text])
205
- expect(table.data_columns.find { |column| column.name == :author_id }.type).
206
- to eq(Cequel::Type[:uuid])
207
- end
208
-
209
- it 'should read index attributes' do
210
- expect(table.data_columns.find { |column| column.name == :author_id }.index_name).
211
- to eq(:posts_author_id_idx)
212
- end
213
-
214
- it 'should leave nil index for non-indexed columns' do
215
- expect(table.data_columns.find { |column| column.name == :title }.index_name).
216
- to be_nil
217
- end
218
-
219
- it 'should read list columns' do
220
- expect(table.data_columns.find { |column| column.name == :categories }).
221
- to be_a(Cequel::Schema::List)
222
- end
223
-
224
- it 'should read list column type' do
225
- expect(table.data_columns.find { |column| column.name == :categories }.type).
226
- to eq(Cequel::Type[:text])
227
- end
228
-
229
- it 'should read set columns' do
230
- expect(table.data_columns.find { |column| column.name == :tags }).
231
- to be_a(Cequel::Schema::Set)
232
- end
233
-
234
- it 'should read set column type' do
235
- expect(table.data_columns.find { |column| column.name == :tags }.type).
236
- to eq(Cequel::Type[:text])
237
- end
238
-
239
- it 'should read map columns' do
240
- expect(table.data_columns.find { |column| column.name == :trackbacks }).
241
- to be_a(Cequel::Schema::Map)
242
- end
243
-
244
- it 'should read map column key type' do
245
- expect(table.data_columns.find { |column| column.name == :trackbacks }.key_type).
246
- to eq(Cequel::Type[:timestamp])
247
- end
248
-
249
- it 'should read map column value type' do
250
- expect(table.data_columns.find { |column| column.name == :trackbacks }.
251
- value_type).to eq(Cequel::Type[:ascii])
252
- end
253
-
254
- end # describe 'reading data columns'
255
-
256
- describe 'reading storage properties' do
257
-
258
- before do
259
- cequel.execute <<-CQL
260
- CREATE TABLE #{table_name} (permalink text PRIMARY KEY)
261
- WITH bloom_filter_fp_chance = 0.02
262
- AND comment = 'Posts table'
263
- AND compaction = {
264
- 'class' : 'SizeTieredCompactionStrategy',
265
- 'bucket_high' : 1.8,
266
- 'max_threshold' : 64,
267
- 'min_sstable_size' : 50,
268
- 'tombstone_compaction_interval' : 2
269
- } AND compression = {
270
- 'sstable_compression' : 'DeflateCompressor',
271
- 'chunk_length_kb' : 128,
272
- 'crc_check_chance' : 0.5
273
- }
274
- CQL
275
- end
276
-
277
- it 'should read float properties' do
278
- expect(table.property(:bloom_filter_fp_chance)).to eq(0.02)
279
- end
280
-
281
- it 'should read string properties' do
282
- expect(table.property(:comment)).to eq('Posts table')
283
- end
284
-
285
- it 'should read and simplify compaction class' do
286
- expect(table.property(:compaction)[:class]).
287
- to eq('SizeTieredCompactionStrategy')
288
- end
289
-
290
- it 'should read float properties from compaction hash' do
291
- expect(table.property(:compaction)[:bucket_high]).to eq(1.8)
292
- end
293
-
294
- it 'should read integer properties from compaction hash' do
295
- expect(table.property(:compaction)[:max_threshold]).to eq(64)
296
- end
297
-
298
- it 'should read and simplify compression class' do
299
- expect(table.property(:compression)[:sstable_compression] ||
300
- table.property(:compression)[:class]).
301
- to eq('DeflateCompressor')
302
-
303
- end
304
-
305
- it 'should read integer properties from compression class' do
306
- expect(table.property(:compression)[:chunk_length_kb]).to eq(128)
307
- end
308
-
309
- it 'should read float properties from compression class' do
310
- expect(table.property(:compression)[:crc_check_chance]).to eq(0.5)
311
- end
312
-
313
- it 'should recognize no compact storage' do
314
- expect(table).not_to be_compact_storage
315
- end
316
-
317
- end # describe 'reading storage properties'
318
-
319
- describe 'skinny-row compact storage' do
320
- before do
321
- cequel.execute <<-CQL
322
- CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
323
- WITH COMPACT STORAGE
324
- CQL
325
- end
326
- subject { table }
327
-
328
- it { is_expected.to be_compact_storage }
329
- its(:partition_key_columns) { should ==
330
- [Cequel::Schema::PartitionKey.new(:permalink, :text)] }
331
- its(:clustering_columns) { should be_empty }
332
- specify { expect(table.data_columns).to contain_exactly(
333
- Cequel::Schema::DataColumn.new(:title, :text),
334
- Cequel::Schema::DataColumn.new(:body, :text)) }
335
- end
336
-
337
- describe 'wide-row compact storage' do
338
- before do
339
- cequel.execute <<-CQL
340
- CREATE TABLE #{table_name} (
341
- blog_subdomain text,
342
- id uuid,
343
- data text,
344
- PRIMARY KEY (blog_subdomain, id)
345
- )
346
- WITH COMPACT STORAGE
347
- CQL
348
- end
349
- subject { table }
350
-
351
- it { is_expected.to be_compact_storage }
352
- its(:partition_key_columns) { should ==
353
- [Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)] }
354
- its(:clustering_columns) { should ==
355
- [Cequel::Schema::ClusteringColumn.new(:id, :uuid)] }
356
- its(:data_columns) { should ==
357
- [Cequel::Schema::DataColumn.new(:data, :text)] }
358
- end
359
-
360
- describe 'skinny-row legacy table', thrift: true do
361
- before do
362
- legacy_connection.execute <<-CQL
363
- CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
364
- CQL
365
- end
366
- subject { table }
367
-
368
- it { is_expected.to be_compact_storage }
369
- its(:partition_key_columns) { is_expected.to eq(
370
- [Cequel::Schema::PartitionKey.new(:permalink, :text)]
371
- ) }
372
- its(:clustering_columns) { is_expected.to be_empty }
373
- its(:data_columns) { is_expected.to match_array(
374
- [Cequel::Schema::DataColumn.new(:title, :text),
375
- Cequel::Schema::DataColumn.new(:body, :text)]
376
- ) }
377
445
  end
378
446
 
379
- describe 'wide-row legacy table', thrift: true do
380
- before do
381
- legacy_connection.execute(<<-CQL2)
382
- CREATE COLUMNFAMILY #{table_name} (blog_subdomain text PRIMARY KEY)
383
- WITH comparator=uuid AND default_validation=text
384
- CQL2
385
- end
386
- subject { table }
387
-
388
- it { is_expected.to be_compact_storage }
389
- its(:partition_key_columns) { is_expected.to eq(
390
- [Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)]
391
- ) }
392
- its(:clustering_columns) { is_expected.to eq(
393
- [Cequel::Schema::ClusteringColumn.new(:column1, :uuid)]
394
- ) }
395
- its(:data_columns) { is_expected.to eq(
396
- [Cequel::Schema::DataColumn.new(:value, :text)]
397
- ) }
447
+ def fetch_table_data(name=table_name)
448
+ cequel.send(:cluster).refresh_schema
449
+ cequel.send(:cluster)
450
+ .keyspace(cequel.name.to_s)
451
+ .table(name.to_s)
398
452
  end
399
453
 
400
- describe 'materialized view exists', thrift: true do
401
- let!(:name) { table_name }
402
- let(:view_name) { "#{name}_view" }
403
- before do
404
- cequel.execute <<-CQL
405
- CREATE TABLE #{table_name} (
406
- blog_subdomain text,
407
- permalink ascii,
408
- PRIMARY KEY (blog_subdomain, permalink)
409
- )
410
- CQL
411
- cequel.execute <<-CQL
412
- CREATE MATERIALIZED VIEW #{view_name} AS
413
- SELECT blog_subdomain, permalink
414
- FROM #{name}
415
- WHERE blog_subdomain IS NOT NULL AND permalink IS NOT NULL
416
- PRIMARY KEY ( blog_subdomain, permalink )
417
- CQL
418
- end
419
- after do
420
- cequel.schema.drop_materialized_view(view_name)
421
- end
422
-
423
- context 'when materialized_view' do
424
- let(:reader) { cequel.schema.get_table_reader(view_name) }
425
- subject { reader }
426
- its(:materialized_view?) { should eq true }
427
- end
428
-
429
- context 'when table' do
430
- let(:reader) { cequel.schema.get_table_reader(name) }
431
- subject { reader }
432
- its(:materialized_view?) { should eq false }
433
- end
454
+ def fetch_view_data(name=view_name)
455
+ cequel.send(:cluster).refresh_schema
456
+ cequel.send(:cluster)
457
+ .keyspace(cequel.name.to_s)
458
+ .materialized_view(name.to_s)
434
459
  end
435
460
  end