cequel 2.1.0 → 3.0.0

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