cassandra 0.12.1 → 0.13.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.
- data/CHANGELOG +5 -0
- data/README.md +4 -4
- data/Rakefile +8 -5
- data/cassandra.gemspec +22 -22
- data/conf/0.8/log4j-server.properties +1 -1
- data/conf/0.8/schema.json +4 -1
- data/conf/0.8/schema.txt +6 -6
- data/lib/cassandra.rb +2 -1
- data/lib/cassandra/0.8/cassandra.rb +16 -1
- data/lib/cassandra/0.8/columns.rb +24 -0
- data/lib/cassandra/0.8/protocol.rb +0 -13
- data/lib/cassandra/1.0.rb +7 -0
- data/lib/cassandra/1.0/cassandra.rb +25 -0
- data/lib/cassandra/1.0/columns.rb +28 -0
- data/lib/cassandra/1.0/protocol.rb +12 -0
- data/lib/cassandra/cassandra.rb +12 -8
- data/lib/cassandra/columns.rb +5 -2
- data/lib/cassandra/composite.rb +118 -0
- data/lib/cassandra/mock.rb +18 -6
- data/test/cassandra_mock_test.rb +43 -0
- data/test/cassandra_test.rb +110 -21
- data/test/composite_type_test.rb +29 -0
- data/vendor/0.8/gen-rb/cassandra_constants.rb +1 -1
- data/vendor/0.8/gen-rb/cassandra_types.rb +9 -1
- data/vendor/1.0/gen-rb/cassandra.rb +2215 -0
- data/vendor/1.0/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/1.0/gen-rb/cassandra_types.rb +857 -0
- metadata +75 -90
@@ -0,0 +1,118 @@
|
|
1
|
+
|
2
|
+
class Cassandra
|
3
|
+
class Composite
|
4
|
+
include ::Comparable
|
5
|
+
attr_reader :parts
|
6
|
+
attr_reader :column_slice
|
7
|
+
|
8
|
+
def initialize(*parts)
|
9
|
+
options = {}
|
10
|
+
if parts.last.is_a?(Hash)
|
11
|
+
options = parts.pop
|
12
|
+
end
|
13
|
+
@column_slice = options[:slice]
|
14
|
+
raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice)
|
15
|
+
|
16
|
+
if parts.length == 1 && parts[0].instance_of?(self.class)
|
17
|
+
@column_slice = parts[0].column_slice
|
18
|
+
@parts = parts[0].parts
|
19
|
+
elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && valid_packed_composite?(parts[0])
|
20
|
+
unpack(parts[0])
|
21
|
+
else
|
22
|
+
@parts = parts
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](*args)
|
27
|
+
return @parts[*args]
|
28
|
+
end
|
29
|
+
|
30
|
+
def pack
|
31
|
+
packed = @parts.map do |part|
|
32
|
+
[part.length].pack('n') + part + "\x00"
|
33
|
+
end
|
34
|
+
if @column_slice
|
35
|
+
part = @parts[-1]
|
36
|
+
packed[-1] = [part.length].pack('n') + part + slice_end_of_component
|
37
|
+
end
|
38
|
+
return packed.join('')
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
return pack
|
43
|
+
end
|
44
|
+
|
45
|
+
def <=>(other)
|
46
|
+
if !other.instance_of?(self.class)
|
47
|
+
return @parts.first <=> other
|
48
|
+
end
|
49
|
+
eoc = slice_end_of_component.unpack('c')[0]
|
50
|
+
other_eoc = other.slice_end_of_component.unpack('c')[0]
|
51
|
+
@parts.zip(other.parts).each do |a, b|
|
52
|
+
next if a == b
|
53
|
+
if a.nil? && b.nil?
|
54
|
+
return eoc <=> other_eoc
|
55
|
+
end
|
56
|
+
|
57
|
+
if a.nil?
|
58
|
+
return @column_slice == :after ? 1 : -1
|
59
|
+
end
|
60
|
+
if b.nil?
|
61
|
+
return other.column_slice == :after ? -1 : 1
|
62
|
+
end
|
63
|
+
return -1 if a < b
|
64
|
+
return 1 if a > b
|
65
|
+
end
|
66
|
+
return 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def inspect
|
70
|
+
return "#<Composite:#{@column_slice} #{@parts.inspect}>"
|
71
|
+
end
|
72
|
+
|
73
|
+
def slice_end_of_component
|
74
|
+
return "\x01" if @column_slice == :after
|
75
|
+
return "\xFF" if @column_slice == :before
|
76
|
+
return "\x00"
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def unpack(packed_string)
|
81
|
+
parts = []
|
82
|
+
end_of_component = nil
|
83
|
+
while packed_string.length > 0
|
84
|
+
length = packed_string.slice(0, 2).unpack('n')[0]
|
85
|
+
parts << packed_string.slice(2, length)
|
86
|
+
end_of_component = packed_string.slice(2 + length, 1)
|
87
|
+
|
88
|
+
packed_string = packed_string.slice(3 + length, packed_string.length)
|
89
|
+
end
|
90
|
+
@column_slice = :after if end_of_component == "\x01"
|
91
|
+
@column_slice = :before if end_of_component == "\xFF"
|
92
|
+
@parts = parts
|
93
|
+
end
|
94
|
+
|
95
|
+
def valid_packed_composite?(packed_string)
|
96
|
+
while packed_string.length > 0
|
97
|
+
length = packed_string.slice(0, 2).unpack('n')[0]
|
98
|
+
return false if length.nil? || length + 3 > packed_string.length
|
99
|
+
|
100
|
+
end_of_component = packed_string.slice(2 + length, 1)
|
101
|
+
if length + 3 != packed_string.length
|
102
|
+
return false if end_of_component != "\x00"
|
103
|
+
end
|
104
|
+
|
105
|
+
packed_string = packed_string.slice(3 + length, packed_string.length)
|
106
|
+
end
|
107
|
+
return true
|
108
|
+
end
|
109
|
+
|
110
|
+
def hash
|
111
|
+
return to_s.hash
|
112
|
+
end
|
113
|
+
|
114
|
+
def eql?(other)
|
115
|
+
return to_s == other.to_s
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/cassandra/mock.rb
CHANGED
@@ -393,11 +393,16 @@ class Cassandra
|
|
393
393
|
if (start_key.nil? || key >= start_key) && (finish_key.nil? || key <= finish_key)
|
394
394
|
if columns
|
395
395
|
#ret[key] = columns.inject(OrderedHash.new){|hash, column_name| hash[column_name] = cf(column_family)[key][column_name]; hash;}
|
396
|
-
|
396
|
+
selected_hash = OrderedHash.new
|
397
|
+
cf(column_family)[key].each do |k, v|
|
398
|
+
selected_hash.[]=(k, v, cf(column_family)[key].timestamps[k]) if columns.include?(k)
|
399
|
+
end
|
400
|
+
ret[key] = columns_to_hash(column_family, selected_hash)
|
397
401
|
ret[key] = apply_count(ret[key], count, reversed)
|
398
402
|
blk.call(key,ret[key]) unless blk.nil?
|
399
403
|
else
|
400
404
|
#ret[key] = apply_range(cf(column_family)[key], column_family, start, finish, !is_super(column_family))
|
405
|
+
start, finish = finish, start if reversed
|
401
406
|
ret[key] = apply_range(columns_to_hash(column_family, cf(column_family)[key]), column_family, start, finish)
|
402
407
|
ret[key] = apply_count(ret[key], count, reversed)
|
403
408
|
blk.call(key,ret[key]) unless blk.nil?
|
@@ -446,7 +451,12 @@ class Cassandra
|
|
446
451
|
|
447
452
|
new_stuff = new_stuff.to_a.inject({}){|h,k| h[k[0].to_s] = k[1]; h }
|
448
453
|
|
449
|
-
|
454
|
+
new_stuff.each { |k,v| old_stuff.[]=(k, v, (Time.now.to_f * 1000000).to_i) }
|
455
|
+
hash = OrderedHash.new
|
456
|
+
old_stuff.sort{ |a,b| a[0] <=> b[0] }.each do |k, v|
|
457
|
+
hash.[]=(k, v, old_stuff.timestamps[k])
|
458
|
+
end
|
459
|
+
hash
|
450
460
|
end
|
451
461
|
|
452
462
|
def columns_to_hash(column_family, columns)
|
@@ -454,15 +464,17 @@ class Cassandra
|
|
454
464
|
output = OrderedHash.new
|
455
465
|
|
456
466
|
columns.each do |column_name, value|
|
467
|
+
timestamp = columns.timestamps[column_name]
|
457
468
|
column = column_class.new(column_name)
|
458
469
|
|
459
470
|
if [Hash, OrderedHash].include?(value.class)
|
460
471
|
output[column] ||= OrderedHash.new
|
461
472
|
value.each do |sub_column, sub_column_value|
|
462
|
-
|
473
|
+
timestamp = value.timestamps[sub_column]
|
474
|
+
output[column].[]=(sub_column_class.new(sub_column), sub_column_value, timestamp)
|
463
475
|
end
|
464
476
|
else
|
465
|
-
output[column_class.new(column_name)
|
477
|
+
output.[]=(column_class.new(column_name), value, timestamp)
|
466
478
|
end
|
467
479
|
end
|
468
480
|
|
@@ -475,7 +487,7 @@ class Cassandra
|
|
475
487
|
keys = keys.reverse if reversed
|
476
488
|
keys = keys[0...count]
|
477
489
|
keys.inject(OrderedHash.new) do |memo, key|
|
478
|
-
memo[
|
490
|
+
memo.[]=(key, row[key], row.timestamps[key])
|
479
491
|
memo
|
480
492
|
end
|
481
493
|
else
|
@@ -489,7 +501,7 @@ class Cassandra
|
|
489
501
|
ret = OrderedHash.new
|
490
502
|
row.keys.each do |key|
|
491
503
|
if (start.nil? || key >= start) && (finish.nil? || key <= finish)
|
492
|
-
ret[
|
504
|
+
ret.[]=(key, row[key], row.timestamps[key])
|
493
505
|
end
|
494
506
|
end
|
495
507
|
ret
|
data/test/cassandra_mock_test.rb
CHANGED
@@ -22,6 +22,12 @@ class CassandraMockTest < CassandraTest
|
|
22
22
|
|
23
23
|
@uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
|
24
24
|
@longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
|
25
|
+
@composites = [
|
26
|
+
Cassandra::Composite.new([5].pack('N'), "zebra"),
|
27
|
+
Cassandra::Composite.new([5].pack('N'), "aardvark"),
|
28
|
+
Cassandra::Composite.new([1].pack('N'), "elephant"),
|
29
|
+
Cassandra::Composite.new([10].pack('N'), "kangaroo"),
|
30
|
+
]
|
25
31
|
end
|
26
32
|
|
27
33
|
def test_setup
|
@@ -57,6 +63,24 @@ class CassandraMockTest < CassandraTest
|
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
66
|
+
def test_get_range_reversed_slice
|
67
|
+
data = 4.times.map { |i| ["body-#{i.to_s}", "v"] }
|
68
|
+
hash = Cassandra::OrderedHash[data]
|
69
|
+
sliced_hash = Cassandra::OrderedHash[data.reverse[1..-1]]
|
70
|
+
|
71
|
+
@twitter.insert(:Statuses, "all-keys", hash)
|
72
|
+
|
73
|
+
columns = @twitter.get_range(
|
74
|
+
:Statuses,
|
75
|
+
:start => sliced_hash.keys.first,
|
76
|
+
:reversed => true
|
77
|
+
)["all-keys"]
|
78
|
+
|
79
|
+
columns.each do |column|
|
80
|
+
assert_equal sliced_hash.shift, column
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
60
84
|
def test_get_range_count
|
61
85
|
data = 3.times.map { |i| ["body-#{i.to_s}", "v"] }
|
62
86
|
hash = Cassandra::OrderedHash[data]
|
@@ -76,4 +100,23 @@ class CassandraMockTest < CassandraTest
|
|
76
100
|
@twitter.insert(:UserRelationships, 'a', ['u1','u2'])
|
77
101
|
}
|
78
102
|
end
|
103
|
+
|
104
|
+
def test_column_timestamps
|
105
|
+
base_time = Time.now
|
106
|
+
@twitter.insert(:Statuses, "time-key", { "body" => "value" })
|
107
|
+
|
108
|
+
results = @twitter.get(:Statuses, "time-key")
|
109
|
+
assert(results.timestamps["body"] / 1000000 >= base_time.to_i)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_supercolumn_timestamps
|
113
|
+
base_time = Time.now
|
114
|
+
@twitter.insert(:StatusRelationships, "time-key", { "super" => { @uuids[1] => "value" }})
|
115
|
+
|
116
|
+
results = @twitter.get(:StatusRelationships, "time-key")
|
117
|
+
assert_nil(results.timestamps["super"])
|
118
|
+
|
119
|
+
columns = results["super"]
|
120
|
+
assert(columns.timestamps[@uuids[1]] / 1000000 >= base_time.to_i)
|
121
|
+
end
|
79
122
|
end
|
data/test/cassandra_test.rb
CHANGED
@@ -21,6 +21,12 @@ class CassandraTest < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
@uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
|
23
23
|
@longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
|
24
|
+
@composites = [
|
25
|
+
Cassandra::Composite.new([5].pack('N'), "zebra"),
|
26
|
+
Cassandra::Composite.new([5].pack('N'), "aardvark"),
|
27
|
+
Cassandra::Composite.new([1].pack('N'), "elephant"),
|
28
|
+
Cassandra::Composite.new([10].pack('N'), "kangaroo"),
|
29
|
+
]
|
24
30
|
end
|
25
31
|
|
26
32
|
def test_inspect
|
@@ -43,7 +49,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
43
49
|
end
|
44
50
|
|
45
51
|
def test_get_key
|
46
|
-
|
52
|
+
|
47
53
|
@twitter.insert(:Users, key, {'body' => 'v', 'user' => 'v'})
|
48
54
|
assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Users, key))
|
49
55
|
assert_equal(['body', 'user'].sort, @twitter.get(:Users, key).timestamps.keys.sort)
|
@@ -280,35 +286,46 @@ class CassandraTest < Test::Unit::TestCase
|
|
280
286
|
|
281
287
|
def test_get_range_block
|
282
288
|
k = key
|
289
|
+
|
290
|
+
values = {}
|
283
291
|
5.times do |i|
|
284
|
-
|
292
|
+
values[k+i.to_s] = {"body-#{i.to_s}" => 'v'}
|
285
293
|
end
|
286
294
|
|
287
|
-
values
|
295
|
+
values.each {|key, columns| @twitter.insert(:Statuses, key, columns) }
|
288
296
|
|
289
297
|
returned_value = @twitter.get_range(:Statuses, :start_key => k.to_s, :key_count => 5) do |key,columns|
|
290
|
-
expected = values.
|
291
|
-
assert_equal expected
|
292
|
-
assert_equal expected[:columns], columns
|
298
|
+
expected = values.delete(key)
|
299
|
+
assert_equal expected, columns
|
293
300
|
end
|
294
301
|
|
295
|
-
|
302
|
+
assert values.length < 5
|
296
303
|
assert_nil returned_value
|
297
304
|
end
|
298
|
-
|
305
|
+
|
299
306
|
def test_get_range_reversed
|
300
307
|
data = 3.times.map { |i| ["body-#{i.to_s}", "v"] }
|
301
308
|
hash = Cassandra::OrderedHash[data]
|
302
309
|
reversed_hash = Cassandra::OrderedHash[data.reverse]
|
303
|
-
|
310
|
+
|
304
311
|
@twitter.insert(:Statuses, "all-keys", hash)
|
305
|
-
|
312
|
+
|
306
313
|
columns = @twitter.get_range(:Statuses, :reversed => true)["all-keys"]
|
307
314
|
columns.each do |column|
|
308
315
|
assert_equal reversed_hash.shift, column
|
309
316
|
end
|
310
317
|
end
|
311
318
|
|
319
|
+
def test_get_range_with_start_key_and_key_count
|
320
|
+
hash = {"name" => "value"}
|
321
|
+
@twitter.insert(:Statuses, "a-key", hash)
|
322
|
+
@twitter.insert(:Statuses, "b-key", hash)
|
323
|
+
@twitter.insert(:Statuses, "c-key", hash)
|
324
|
+
|
325
|
+
results = @twitter.get_range(:Statuses, :start_key => "b-key", :key_count => 1)
|
326
|
+
assert_equal ["b-key"], results.keys
|
327
|
+
end
|
328
|
+
|
312
329
|
def test_each_key
|
313
330
|
k = key
|
314
331
|
keys_yielded = []
|
@@ -490,12 +507,12 @@ class CassandraTest < Test::Unit::TestCase
|
|
490
507
|
|
491
508
|
def test_count_columns
|
492
509
|
columns = (1..200).inject(Hash.new){|h,v| h['column' + v.to_s] = v.to_s; h;}
|
493
|
-
|
510
|
+
|
494
511
|
@twitter.insert(:Statuses, key, columns)
|
495
512
|
assert_equal 200, @twitter.count_columns(:Statuses, key, :count => 200)
|
496
|
-
assert_equal 100, @twitter.count_columns(:Statuses, key)
|
513
|
+
assert_equal 100, @twitter.count_columns(:Statuses, key)
|
497
514
|
assert_equal 55, @twitter.count_columns(:Statuses, key, :count => 55)
|
498
|
-
|
515
|
+
|
499
516
|
end
|
500
517
|
|
501
518
|
def test_count_super_columns
|
@@ -539,40 +556,43 @@ class CassandraTest < Test::Unit::TestCase
|
|
539
556
|
@twitter.insert(:Users, k + '3', {'body' => 'bogus', 'user' => 'v3'})
|
540
557
|
@twitter.insert(:Users, k + '3', {'body' => 'v3', 'location' => 'v3'})
|
541
558
|
@twitter.insert(:Statuses, k + '3', {'body' => 'v'})
|
559
|
+
@twitter.add(:UserCounters, 'bob', 5, 'tweet_count') if CASSANDRA_VERSION.to_f >= 0.8
|
542
560
|
|
543
561
|
assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Written
|
544
562
|
assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Written
|
545
563
|
assert_equal({}, @twitter.get(:Users, k + '2')) # Not yet written
|
546
564
|
assert_equal({}, @twitter.get(:Statuses, k + '3')) # Not yet written
|
565
|
+
assert_equal({}, @twitter.get(:UserCounters, 'bob')) if CASSANDRA_VERSION.to_f >= 0.8 # Not yet written
|
547
566
|
|
548
|
-
@twitter.remove(:Users, k + '1') # Full row
|
567
|
+
@twitter.remove(:Users, k + '1') # Full row
|
549
568
|
assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Not yet removed
|
550
569
|
|
551
570
|
@twitter.remove(:Users, k + '0', 'delete_me') # A single column of the row
|
552
571
|
assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Not yet removed
|
553
|
-
|
572
|
+
|
554
573
|
@twitter.remove(:Users, k + '4')
|
555
574
|
@twitter.insert(:Users, k + '4', {'body' => 'v4', 'user' => 'v4'})
|
556
575
|
assert_equal({}, @twitter.get(:Users, k + '4')) # Not yet written
|
557
576
|
|
558
577
|
# SuperColumns
|
559
578
|
# Add and delete new sub columns to the user timeline supercolumn
|
560
|
-
@twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
|
579
|
+
@twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
|
561
580
|
@twitter.remove(:StatusRelationships, k, 'user_timelines' , subcolumn_to_delete ) # Delete the first of the initial_subcolumns from the user_timeline supercolumn
|
562
581
|
assert_equal(initial_subcolumns, @twitter.get(:StatusRelationships, k, 'user_timelines')) # No additions or deletes reflected yet
|
563
|
-
# Delete a complete supercolumn
|
582
|
+
# Delete a complete supercolumn
|
564
583
|
@twitter.remove(:StatusRelationships, k, 'dummy_supercolumn' ) # Delete the full dummy supercolumn
|
565
|
-
assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
|
584
|
+
assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
|
566
585
|
end
|
567
586
|
|
568
587
|
assert_equal({'body' => 'v2', 'user' => 'v2'}, @twitter.get(:Users, k + '2')) # Written
|
569
588
|
assert_equal({'body' => 'v3', 'user' => 'v3', 'location' => 'v3'}, @twitter.get(:Users, k + '3')) # Written and compacted
|
570
589
|
assert_equal({'body' => 'v4', 'user' => 'v4'}, @twitter.get(:Users, k + '4')) # Written
|
571
590
|
assert_equal({'body' => 'v'}, @twitter.get(:Statuses, k + '3')) # Written
|
591
|
+
assert_equal({'tweet_count' => 5}, @twitter.get(:UserCounters, 'bob')) if CASSANDRA_VERSION.to_f >= 0.8 # Written
|
572
592
|
assert_equal({}, @twitter.get(:Users, k + '1')) # Removed
|
573
|
-
|
593
|
+
|
574
594
|
assert_equal({ 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # 'delete_me' column removed
|
575
|
-
|
595
|
+
|
576
596
|
|
577
597
|
assert_equal({'body' => 'v2', 'user' => 'v2'}.keys.sort, @twitter.get(:Users, k + '2').timestamps.keys.sort) # Written
|
578
598
|
assert_equal({'body' => 'v3', 'user' => 'v3', 'location' => 'v3'}.keys.sort, @twitter.get(:Users, k + '3').timestamps.keys.sort) # Written and compacted
|
@@ -582,7 +602,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
582
602
|
# Final result: initial_subcolumns - initial_subcolumns.first + new_subcolumns
|
583
603
|
resulting_subcolumns = initial_subcolumns.merge(new_subcolumns).reject{|k2,v| k2 == subcolumn_to_delete }
|
584
604
|
assert_equal(resulting_subcolumns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
|
585
|
-
assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
|
605
|
+
assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
|
586
606
|
|
587
607
|
end
|
588
608
|
|
@@ -823,6 +843,75 @@ class CassandraTest < Test::Unit::TestCase
|
|
823
843
|
assert_equal(1, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'today'))
|
824
844
|
assert_equal(2, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'tomorrow'))
|
825
845
|
end
|
846
|
+
|
847
|
+
def test_reading_rows_with_super_column_counter
|
848
|
+
assert_nil @twitter.add(:UserCounterAggregates, 'bob', 1, 'DAU', 'today')
|
849
|
+
assert_nil @twitter.add(:UserCounterAggregates, 'bob', 2, 'DAU', 'tomorrow')
|
850
|
+
result = @twitter.get(:UserCounterAggregates, 'bob')
|
851
|
+
assert_equal(1, result.size)
|
852
|
+
assert_equal(2, result.first.size)
|
853
|
+
assert_equal("DAU", result.first[0])
|
854
|
+
assert_equal(1, result.first[1]["today"])
|
855
|
+
assert_equal(2, result.first[1]["tomorrow"])
|
856
|
+
end
|
857
|
+
|
858
|
+
def test_composite_column_type_conversion
|
859
|
+
columns = {}
|
860
|
+
@composites.each_with_index do |c, index|
|
861
|
+
columns[c] = "value-#{index}"
|
862
|
+
end
|
863
|
+
@type_conversions.insert(:CompositeColumnConversion, key, columns)
|
864
|
+
columns_in_order = [
|
865
|
+
Cassandra::Composite.new([1].pack('N'), "elephant"),
|
866
|
+
Cassandra::Composite.new([5].pack('N'), "aardvark"),
|
867
|
+
Cassandra::Composite.new([5].pack('N'), "zebra"),
|
868
|
+
Cassandra::Composite.new([10].pack('N'), "kangaroo"),
|
869
|
+
]
|
870
|
+
assert_equal(columns_in_order, @type_conversions.get(:CompositeColumnConversion, key).keys)
|
871
|
+
|
872
|
+
column_slice = @type_conversions.get(:CompositeColumnConversion, key,
|
873
|
+
:start => Cassandra::Composite.new([1].pack('N')),
|
874
|
+
:finish => Cassandra::Composite.new([10].pack('N')),
|
875
|
+
).keys
|
876
|
+
assert_equal(columns_in_order[0..-2], column_slice)
|
877
|
+
|
878
|
+
column_slice = @type_conversions.get(:CompositeColumnConversion, key,
|
879
|
+
:start => Cassandra::Composite.new([5].pack('N')),
|
880
|
+
:finish => Cassandra::Composite.new([5].pack('N'), :slice => :after),
|
881
|
+
).keys
|
882
|
+
assert_equal(columns_in_order[1..2], column_slice)
|
883
|
+
|
884
|
+
column_slice = @type_conversions.get(:CompositeColumnConversion, key,
|
885
|
+
:start => Cassandra::Composite.new([5].pack('N'), :slice => :after).to_s,
|
886
|
+
).keys
|
887
|
+
assert_equal([columns_in_order[-1]], column_slice)
|
888
|
+
|
889
|
+
column_slice = @type_conversions.get(:CompositeColumnConversion, key,
|
890
|
+
:finish => Cassandra::Composite.new([10].pack('N'), :slice => :before).to_s,
|
891
|
+
).keys
|
892
|
+
assert_equal(columns_in_order[0..-2], column_slice)
|
893
|
+
|
894
|
+
assert_equal('value-2', @type_conversions.get(:CompositeColumnConversion, key, columns_in_order.first))
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
def test_column_timestamps
|
899
|
+
base_time = Time.now
|
900
|
+
@twitter.insert(:Statuses, "time-key", { "body" => "value" })
|
901
|
+
|
902
|
+
results = @twitter.get(:Statuses, "time-key")
|
903
|
+
assert(results.timestamps["body"] / 1000000 >= base_time.to_i)
|
904
|
+
end
|
905
|
+
|
906
|
+
def test_supercolumn_timestamps
|
907
|
+
base_time = Time.now
|
908
|
+
@twitter.insert(:StatusRelationships, "time-key", { "super" => { @uuids[1] => "value" }})
|
909
|
+
|
910
|
+
results = @twitter.get(:StatusRelationships, "time-key")
|
911
|
+
assert_nil(results.timestamps["super"])
|
912
|
+
|
913
|
+
columns = results["super"]
|
914
|
+
assert(columns.timestamps[@uuids[1]] / 1000000 >= base_time.to_i)
|
826
915
|
end
|
827
916
|
|
828
917
|
private
|