cassandra 0.4 → 0.5
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.tar.gz.sig +0 -0
- data/CHANGELOG +2 -0
- data/Manifest +4 -4
- data/README +11 -11
- data/Rakefile +58 -3
- data/cassandra.gemspec +10 -7
- data/conf/storage-conf.xml +28 -15
- data/lib/cassandra.rb +3 -3
- data/lib/cassandra/array.rb +1 -1
- data/lib/cassandra/cassandra.rb +199 -216
- data/lib/cassandra/{helper.rb → columns.rb} +16 -15
- data/lib/cassandra/comparable.rb +1 -1
- data/lib/cassandra/constants.rb +4 -0
- data/lib/cassandra/long.rb +16 -14
- data/lib/cassandra/ordered_hash.rb +1 -1
- data/lib/cassandra/protocol.rb +86 -0
- data/lib/cassandra/safe_client.rb +1 -1
- data/lib/cassandra/time.rb +8 -6
- data/lib/cassandra/uuid.rb +93 -28
- data/test/{cassandra_client_test.rb → cassandra_test.rb} +54 -54
- data/test/comparable_types_test.rb +5 -6
- data/test/test_helper.rb +14 -0
- data/vendor/gen-rb/cassandra.rb +109 -417
- data/vendor/gen-rb/cassandra_types.rb +35 -15
- metadata +22 -13
- metadata.gz.sig +0 -0
- data/lib/cassandra/serialization.rb +0 -57
- data/quickstart.sh +0 -12
@@ -1,8 +1,7 @@
|
|
1
|
-
class Cassandra
|
2
1
|
|
2
|
+
class Cassandra
|
3
3
|
# A bunch of crap, mostly related to introspecting on column types
|
4
|
-
module
|
5
|
-
|
4
|
+
module Columns #:nodoc:
|
6
5
|
private
|
7
6
|
|
8
7
|
def is_super(column_family)
|
@@ -19,12 +18,13 @@ class Cassandra
|
|
19
18
|
|
20
19
|
def column_name_class_for_key(column_family, comparator_key)
|
21
20
|
property = column_family_property(column_family, comparator_key)
|
22
|
-
property =~ /.*\.(.*?)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
property =~ /.*\.(.*?)$/
|
22
|
+
case $1
|
23
|
+
when "LongType" then Long
|
24
|
+
when "LexicalUUIDType", "TimeUUIDType" then UUID
|
25
|
+
else
|
26
|
+
String # UTF8, Ascii, Bytes, anything else
|
27
|
+
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def column_family_property(column_family, key)
|
@@ -53,11 +53,12 @@ class Cassandra
|
|
53
53
|
def columns_to_hash_for_classes(columns, column_name_class, sub_column_name_class = nil)
|
54
54
|
hash = OrderedHash.new
|
55
55
|
Array(columns).each do |c|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
c = c.super_column || c.column if c.is_a?(CassandraThrift::ColumnOrSuperColumn)
|
57
|
+
hash[column_name_class.new(c.name)] = case c
|
58
|
+
when CassandraThrift::SuperColumn
|
59
|
+
columns_to_hash_for_classes(c.columns, sub_column_name_class) # Pop the class stack, and recurse
|
60
|
+
when CassandraThrift::Column
|
61
|
+
c.value
|
61
62
|
end
|
62
63
|
end
|
63
64
|
hash
|
@@ -70,7 +71,7 @@ class Cassandra
|
|
70
71
|
|
71
72
|
def hash_to_columns_without_assertion(column_family, hash, timestamp)
|
72
73
|
hash.map do |column, value|
|
73
|
-
CassandraThrift::Column.new(:name => column.to_s, :value =>
|
74
|
+
CassandraThrift::Column.new(:name => column.to_s, :value => value, :timestamp => timestamp)
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
data/lib/cassandra/comparable.rb
CHANGED
data/lib/cassandra/constants.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
|
2
2
|
class Cassandra
|
3
|
+
# A helper module you can include in your own class. Makes it easier
|
4
|
+
# to work with Cassandra subclasses.
|
3
5
|
module Constants
|
6
|
+
include Cassandra::Consistency
|
7
|
+
|
4
8
|
UUID = Cassandra::UUID
|
5
9
|
Long = Cassandra::Long
|
6
10
|
OrderedHash = Cassandra::OrderedHash
|
data/lib/cassandra/long.rb
CHANGED
@@ -2,38 +2,40 @@
|
|
2
2
|
class Cassandra
|
3
3
|
# A temporally-ordered Long class for use in Cassandra column names
|
4
4
|
class Long < Comparable
|
5
|
-
|
6
|
-
MAX = 2**64
|
7
|
-
|
5
|
+
|
8
6
|
def initialize(bytes = nil)
|
9
7
|
case bytes
|
10
8
|
when String
|
11
9
|
raise TypeError, "8 bytes required" if bytes.size != 8
|
12
10
|
@bytes = bytes
|
13
11
|
when Integer
|
14
|
-
raise TypeError, "Integer must be between 0 and 2**64" if bytes < 0 or bytes >
|
15
|
-
@bytes = [bytes].pack("
|
12
|
+
raise TypeError, "Integer must be between 0 and 2**64" if bytes < 0 or bytes > 2**64
|
13
|
+
@bytes = [bytes >> 32, bytes % 2**32].pack("NN")
|
16
14
|
when NilClass
|
17
15
|
# Time.stamp is 52 bytes, so we have 12 bytes of entropy left over
|
18
|
-
|
16
|
+
int = (Time.stamp << 12) + rand(2**12)
|
17
|
+
@bytes = [int >> 32, int % 2**32].pack("NN")
|
19
18
|
else
|
20
19
|
raise TypeError, "Can't convert from #{bytes.class}"
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
23
|
def to_i
|
25
|
-
@to_i ||=
|
24
|
+
@to_i ||= begin
|
25
|
+
ints = @bytes.unpack("NN")
|
26
|
+
(ints[0] << 32) +
|
27
|
+
ints[1]
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
31
|
def inspect
|
29
|
-
ints = @bytes.unpack("Q")
|
30
32
|
"<Cassandra::Long##{object_id} time: #{
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
Time.at((to_i >> 12) / 1_000_000).inspect
|
34
|
+
}, usecs: #{
|
35
|
+
(to_i >> 12) % 1_000_000
|
36
|
+
}, jitter: #{
|
37
|
+
to_i % 2**12
|
38
|
+
}>"
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
@@ -25,7 +25,7 @@ class Cassandra
|
|
25
25
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
26
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
27
|
|
28
|
-
class OrderedHash < Hash
|
28
|
+
class OrderedHash < Hash #:nodoc: all
|
29
29
|
require 'enumerator'
|
30
30
|
|
31
31
|
def self.[](*array)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
class Cassandra
|
3
|
+
# Inner methods for actually doing the Thrift calls
|
4
|
+
module Protocol #:nodoc:
|
5
|
+
private
|
6
|
+
|
7
|
+
def _insert(mutation, consistency)
|
8
|
+
case mutation
|
9
|
+
when CassandraThrift::BatchMutationSuper then @client.batch_insert_super_column(@keyspace, mutation, consistency)
|
10
|
+
when CassandraThrift::BatchMutation then @client.batch_insert(@keyspace, mutation, consistency)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def _remove(column_family, key, column, sub_column, consistency, timestamp)
|
15
|
+
column_path_or_parent = if is_super(column_family)
|
16
|
+
CassandraThrift::ColumnPath.new(:column_family => column_family, :super_column => column, :column => sub_column)
|
17
|
+
else
|
18
|
+
CassandraThrift::ColumnPath.new(:column_family => column_family, :column => column)
|
19
|
+
end
|
20
|
+
@client.remove(@keyspace, key, column_path_or_parent, timestamp, consistency)
|
21
|
+
end
|
22
|
+
|
23
|
+
def _count_columns(column_family, key, super_column, consistency)
|
24
|
+
@client.get_count(@keyspace, key,
|
25
|
+
CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => super_column),
|
26
|
+
consistency
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _get_columns(column_family, key, columns, sub_columns, consistency)
|
31
|
+
result = if is_super(column_family)
|
32
|
+
if sub_columns
|
33
|
+
columns_to_hash(column_family, @client.get_slice(@keyspace, key,
|
34
|
+
CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => columns),
|
35
|
+
CassandraThrift::SlicePredicate.new(:column_names => sub_columns),
|
36
|
+
consistency))
|
37
|
+
else
|
38
|
+
columns_to_hash(column_family, @client.get_slice(@keyspace, key,
|
39
|
+
CassandraThrift::ColumnParent.new(:column_family => column_family),
|
40
|
+
CassandraThrift::SlicePredicate.new(:column_names => columns),
|
41
|
+
consistency))
|
42
|
+
end
|
43
|
+
else
|
44
|
+
columns_to_hash(column_family, @client.get_slice(@keyspace, key,
|
45
|
+
CassandraThrift::ColumnParent.new(:column_family => column_family),
|
46
|
+
CassandraThrift::SlicePredicate.new(:column_names => columns),
|
47
|
+
consistency))
|
48
|
+
end
|
49
|
+
sub_columns || columns.map { |name| result[name] }
|
50
|
+
end
|
51
|
+
|
52
|
+
def _get(column_family, key, column, sub_column, count, start, finish, reversed, consistency)
|
53
|
+
# Single values; count and range parameters have no effect
|
54
|
+
if is_super(column_family) and sub_column
|
55
|
+
column_path = CassandraThrift::ColumnPath.new(:column_family => column_family, :super_column => column, :column => sub_column)
|
56
|
+
@client.get(@keyspace, key, column_path, consistency).column.value
|
57
|
+
elsif !is_super(column_family) and column
|
58
|
+
column_path = CassandraThrift::ColumnPath.new(:column_family => column_family, :column => column)
|
59
|
+
@client.get(@keyspace, key, column_path, consistency).column.value
|
60
|
+
|
61
|
+
# Slices
|
62
|
+
else
|
63
|
+
# FIXME Comparable types in range are not enforced
|
64
|
+
predicate = CassandraThrift::SlicePredicate.new(:slice_range =>
|
65
|
+
CassandraThrift::SliceRange.new(
|
66
|
+
:is_ascending => !reversed,
|
67
|
+
:count => count,
|
68
|
+
:start => start.to_s,
|
69
|
+
:finish => finish.to_s))
|
70
|
+
|
71
|
+
if is_super(column_family) and column
|
72
|
+
column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => column)
|
73
|
+
sub_columns_to_hash(column_family, @client.get_slice(@keyspace, key, column_parent, predicate, consistency))
|
74
|
+
else
|
75
|
+
column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
|
76
|
+
columns_to_hash(column_family, @client.get_slice(@keyspace, key, column_parent, predicate, consistency))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def _get_range(column_family, start, finish, count, consistency)
|
82
|
+
# FIXME Consistency is ignored
|
83
|
+
@client.get_key_range(@keyspace, column_family, start.to_s, finish.to_s, count)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/cassandra/time.rb
CHANGED
data/lib/cassandra/uuid.rb
CHANGED
@@ -1,44 +1,109 @@
|
|
1
1
|
|
2
2
|
class Cassandra
|
3
|
-
|
3
|
+
|
4
|
+
# UUID format version 1, as specified in RFC 4122, with jitter in place of the mac address and sequence counter.
|
4
5
|
class UUID < Comparable
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
|
7
|
+
class InvalidVersion < StandardError #:nodoc:
|
8
|
+
end
|
9
|
+
|
10
|
+
GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000 # Oct 15, 1582
|
8
11
|
|
9
|
-
|
12
|
+
VARIANT = 0b1000_0000_0000_0000
|
13
|
+
|
14
|
+
def initialize(bytes = nil)
|
10
15
|
case bytes
|
11
16
|
when String
|
12
|
-
|
13
|
-
|
17
|
+
case bytes.size
|
18
|
+
when 16
|
19
|
+
@bytes = bytes
|
20
|
+
when 36
|
21
|
+
elements = bytes.split("-")
|
22
|
+
raise TypeError, "Malformed UUID representation" if elements.size != 5
|
23
|
+
@bytes = elements.join.to_a.pack('H32')
|
24
|
+
else
|
25
|
+
raise TypeError, "16 bytes required for byte array, or 36 characters required for UUID representation"
|
26
|
+
end
|
27
|
+
|
14
28
|
when Integer
|
15
|
-
raise TypeError, "Integer must be between 0 and 2**128" if bytes < 0 or bytes >
|
16
|
-
@bytes = [
|
17
|
-
|
18
|
-
|
29
|
+
raise TypeError, "Integer must be between 0 and 2**128" if bytes < 0 or bytes > 2**128
|
30
|
+
@bytes = [
|
31
|
+
(bytes >> 96) & 0xFFFF_FFFF,
|
32
|
+
(bytes >> 64) & 0xFFFF_FFFF,
|
33
|
+
(bytes >> 32) & 0xFFFF_FFFF,
|
34
|
+
bytes & 0xFFFF_FFFF
|
35
|
+
].pack("NNNN")
|
36
|
+
|
37
|
+
when NilClass, Time
|
38
|
+
time = (bytes || Time).stamp * 10 + GREGORIAN_EPOCH_OFFSET
|
39
|
+
# See http://github.com/spectra/ruby-uuid/
|
40
|
+
@bytes = [
|
41
|
+
time & 0xFFFF_FFFF,
|
42
|
+
time >> 32,
|
43
|
+
((time >> 48) & 0x0FFF) | 0x1000,
|
44
|
+
# Top 3 bytes reserved
|
45
|
+
rand(2**13) | VARIANT,
|
46
|
+
rand(2**16),
|
47
|
+
rand(2**32)
|
48
|
+
].pack("NnnnnN")
|
49
|
+
|
19
50
|
else
|
20
51
|
raise TypeError, "Can't convert from #{bytes.class}"
|
21
52
|
end
|
22
53
|
end
|
23
|
-
|
54
|
+
|
24
55
|
def to_i
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
56
|
+
ints = @bytes.unpack("NNNN")
|
57
|
+
(ints[0] << 96) +
|
58
|
+
(ints[1] << 64) +
|
59
|
+
(ints[2] << 32) +
|
60
|
+
ints[3]
|
61
|
+
end
|
62
|
+
|
63
|
+
def version
|
64
|
+
time_high = @bytes.unpack("NnnQ")[2]
|
65
|
+
version = (time_high & 0xF000).to_s(16)[0].chr.to_i
|
66
|
+
version > 0 and version < 6 ? version : -1
|
67
|
+
end
|
68
|
+
|
69
|
+
def variant
|
70
|
+
@bytes.unpack('QnnN')[1] >> 13
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_guid
|
74
|
+
elements = @bytes.unpack("NnnCCa6")
|
75
|
+
node = elements[-1].unpack('C*')
|
76
|
+
elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
|
77
|
+
"%08x-%04x-%04x-%02x%02x-%s" % elements
|
29
78
|
end
|
30
79
|
|
31
|
-
def
|
32
|
-
|
80
|
+
def seconds
|
81
|
+
total_usecs / 1_000_000
|
82
|
+
end
|
83
|
+
|
84
|
+
def usecs
|
85
|
+
total_usecs % 1_000_000
|
86
|
+
end
|
87
|
+
|
88
|
+
def <=>(other)
|
89
|
+
total_usecs <=> other.send(:total_usecs)
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect(long = false)
|
33
93
|
"<Cassandra::UUID##{object_id} time: #{
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
94
|
+
Time.at(seconds).inspect
|
95
|
+
}, usecs: #{
|
96
|
+
usecs
|
97
|
+
} jitter: #{
|
98
|
+
@bytes.unpack('QQ')[1]
|
99
|
+
}" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" : ">")
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def total_usecs
|
105
|
+
elements = @bytes.unpack("NnnQ")
|
106
|
+
(elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
|
107
|
+
end
|
108
|
+
end
|
44
109
|
end
|
@@ -1,8 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'test/unit'
|
3
|
-
require "#{File.expand_path(File.dirname(__FILE__))}/../lib/cassandra"
|
4
|
-
|
5
|
-
begin; require 'ruby-debug'; rescue LoadError; end
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
6
2
|
|
7
3
|
class CassandraTest < Test::Unit::TestCase
|
8
4
|
include Cassandra::Constants
|
@@ -12,6 +8,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
12
8
|
@twitter.clear_keyspace!
|
13
9
|
@blogs = Cassandra.new('Multiblog', '127.0.0.1')
|
14
10
|
@blogs.clear_keyspace!
|
11
|
+
@uuids = (0..6).map {|i| UUID.new(Time.at(2**(24+i))) }
|
15
12
|
end
|
16
13
|
|
17
14
|
def test_inspect
|
@@ -38,14 +35,14 @@ class CassandraTest < Test::Unit::TestCase
|
|
38
35
|
|
39
36
|
def test_get_key_name_sorted_preserving_order
|
40
37
|
# In-order hash is preserved
|
41
|
-
hash = OrderedHash['a',
|
38
|
+
hash = OrderedHash['a', '', 'b', '', 'c', '', 'd', '',]
|
42
39
|
@twitter.insert(:Users, key, hash)
|
43
40
|
assert_equal(hash.keys, @twitter.get(:Users, key).keys)
|
44
41
|
|
45
42
|
@twitter.remove(:Users, key)
|
46
43
|
|
47
44
|
# Out-of-order hash is returned sorted
|
48
|
-
hash = OrderedHash['b',
|
45
|
+
hash = OrderedHash['b', '', 'c', '', 'd', '', 'a', '']
|
49
46
|
@twitter.insert(:Users, key, hash)
|
50
47
|
assert_equal(hash.keys.sort, @twitter.get(:Users, key).keys)
|
51
48
|
assert_not_equal(hash.keys, @twitter.get(:Users, key).keys)
|
@@ -57,6 +54,12 @@ class CassandraTest < Test::Unit::TestCase
|
|
57
54
|
assert_equal({}, @twitter.get(:Statuses, 'bogus'))
|
58
55
|
end
|
59
56
|
|
57
|
+
def test_get_with_count
|
58
|
+
@twitter.insert(:Statuses, key, {'1' => 'v', '2' => 'v', '3' => 'v'})
|
59
|
+
assert_equal 1, @twitter.get(:Statuses, key, :count => 1).size
|
60
|
+
assert_equal 2, @twitter.get(:Statuses, key, :count => 2).size
|
61
|
+
end
|
62
|
+
|
60
63
|
def test_get_value
|
61
64
|
@twitter.insert(:Statuses, key, {'body' => 'v'})
|
62
65
|
assert_equal 'v', @twitter.get(:Statuses, key, 'body')
|
@@ -65,15 +68,9 @@ class CassandraTest < Test::Unit::TestCase
|
|
65
68
|
assert @twitter.exists?(:Statuses, key, 'body')
|
66
69
|
assert_nil @twitter.exists?(:Statuses, 'bogus', 'body')
|
67
70
|
end
|
68
|
-
|
69
|
-
def test_get_value_nil
|
70
|
-
@twitter.insert(:Statuses, key, {'body' => nil})
|
71
|
-
assert_nil @twitter.get(:Statuses, key, 'body')
|
72
|
-
assert @twitter.exists?(:Statuses, key, 'body')
|
73
|
-
end
|
74
|
-
|
71
|
+
|
75
72
|
def test_get_super_key
|
76
|
-
columns = {'user_timelines' => {
|
73
|
+
columns = {'user_timelines' => {@uuids[4] => '4', @uuids[5] => '5'}}
|
77
74
|
@twitter.insert(:StatusRelationships, key, columns)
|
78
75
|
assert_equal(columns, @twitter.get(:StatusRelationships, key))
|
79
76
|
assert_equal({}, @twitter.get(:StatusRelationships, 'bogus'))
|
@@ -81,57 +78,60 @@ class CassandraTest < Test::Unit::TestCase
|
|
81
78
|
|
82
79
|
def test_get_several_super_keys
|
83
80
|
columns = {
|
84
|
-
'user_timelines' => {
|
85
|
-
'mentions_timelines' => {
|
81
|
+
'user_timelines' => {@uuids[1] => 'v1'},
|
82
|
+
'mentions_timelines' => {@uuids[2] => 'v2'}}
|
86
83
|
@twitter.insert(:StatusRelationships, key, columns)
|
87
84
|
|
88
85
|
assert_equal(columns, @twitter.get(:StatusRelationships, key))
|
89
86
|
assert_equal({}, @twitter.get(:StatusRelationships, 'bogus'))
|
90
87
|
end
|
91
88
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@twitter.insert(:StatusRelationships, key,
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
89
|
+
def test_get_super_sub_keys_with_count
|
90
|
+
@twitter.insert(:StatusRelationships, key,
|
91
|
+
{'user_timelines' => {@uuids[1] => 'v1', @uuids[2] => 'v2', @uuids[3] => 'v3'}})
|
92
|
+
assert_equal({@uuids[1] => 'v1'},
|
93
|
+
@twitter.get(:StatusRelationships, key, "user_timelines", :count => 1))
|
94
|
+
assert_equal({@uuids[3] => 'v3'},
|
95
|
+
@twitter.get(:StatusRelationships, key, "user_timelines", :count => 1, :reversed => true))
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_get_super_sub_keys_with_ranges
|
99
|
+
@twitter.insert(:StatusRelationships, key,
|
100
|
+
{'user_timelines' => {
|
101
|
+
@uuids[1] => 'v1',
|
102
|
+
@uuids[2] => 'v2',
|
103
|
+
@uuids[3] => 'v3',
|
104
|
+
@uuids[4] => 'v4',
|
105
|
+
@uuids[5] => 'v5'}})
|
106
|
+
|
107
107
|
keys = @twitter.get(:StatusRelationships, key, "user_timelines").keys
|
108
|
-
assert_equal keys.sort, keys
|
109
|
-
|
110
|
-
assert_equal(
|
111
|
-
assert_equal
|
108
|
+
assert_equal keys.sort, keys
|
109
|
+
assert_equal({@uuids[1] => 'v1'}, @twitter.get(:StatusRelationships, key, "user_timelines", :finish => @uuids[2], :count => 1))
|
110
|
+
assert_equal({@uuids[2] => 'v2'}, @twitter.get(:StatusRelationships, key, "user_timelines", :start => @uuids[2], :count => 1))
|
111
|
+
assert_equal 4, @twitter.get(:StatusRelationships, key, "user_timelines", :start => @uuids[2], :finish => @uuids[5]).size
|
112
112
|
end
|
113
113
|
|
114
114
|
def test_get_super_sub_key
|
115
|
-
columns = {
|
115
|
+
columns = {@uuids[1] => 'v1', @uuids[2] => 'v2'}
|
116
116
|
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
117
117
|
assert_equal(columns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
|
118
118
|
assert_equal({}, @twitter.get(:StatusRelationships, 'bogus', 'user_timelines'))
|
119
119
|
end
|
120
120
|
|
121
121
|
def test_get_super_value
|
122
|
-
columns = {
|
122
|
+
columns = {@uuids[1] => 'v1'}
|
123
123
|
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
124
|
-
assert_equal('
|
124
|
+
assert_equal('v1', @twitter.get(:StatusRelationships, key, 'user_timelines', columns.keys.first))
|
125
125
|
assert_nil @twitter.get(:StatusRelationships, 'bogus', 'user_timelines', columns.keys.first)
|
126
126
|
end
|
127
127
|
|
128
|
-
def
|
128
|
+
def test_get_range
|
129
129
|
@twitter.insert(:Statuses, '2', {'body' => '1'})
|
130
130
|
@twitter.insert(:Statuses, '3', {'body' => '1'})
|
131
131
|
@twitter.insert(:Statuses, '4', {'body' => '1'})
|
132
132
|
@twitter.insert(:Statuses, '5', {'body' => '1'})
|
133
133
|
@twitter.insert(:Statuses, '6', {'body' => '1'})
|
134
|
-
assert_equal(['3', '4', '5'], @twitter.
|
134
|
+
assert_equal(['3', '4', '5'], @twitter.get_range(:Statuses, :start => '3', :finish => '5'))
|
135
135
|
end
|
136
136
|
|
137
137
|
def test_multi_get
|
@@ -151,7 +151,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
151
151
|
|
152
152
|
@twitter.remove(:Statuses, key)
|
153
153
|
assert_equal({}, @twitter.get(:Statuses, key))
|
154
|
-
assert_equal 0, @twitter.
|
154
|
+
assert_equal 0, @twitter.count_range(:Statuses)
|
155
155
|
end
|
156
156
|
|
157
157
|
def test_remove_value
|
@@ -161,19 +161,19 @@ class CassandraTest < Test::Unit::TestCase
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def test_remove_super_key
|
164
|
-
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {
|
164
|
+
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {@uuids[1] => 'v1'}})
|
165
165
|
@twitter.remove(:StatusRelationships, key)
|
166
166
|
assert_equal({}, @twitter.get(:StatusRelationships, key))
|
167
167
|
end
|
168
168
|
|
169
169
|
def test_remove_super_sub_key
|
170
|
-
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {
|
170
|
+
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {@uuids[1] => 'v1'}})
|
171
171
|
@twitter.remove(:StatusRelationships, key, 'user_timelines')
|
172
172
|
assert_equal({}, @twitter.get(:StatusRelationships, key, 'user_timelines'))
|
173
173
|
end
|
174
174
|
|
175
175
|
def test_remove_super_value
|
176
|
-
columns = {
|
176
|
+
columns = {@uuids[1] => 'v1'}
|
177
177
|
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
178
178
|
@twitter.remove(:StatusRelationships, key, 'user_timelines', columns.keys.first)
|
179
179
|
assert_nil @twitter.get(:StatusRelationships, key, 'user_timelines', columns.keys.first)
|
@@ -184,7 +184,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
184
184
|
@twitter.insert(:Statuses, key + "2", {'body' => '2'})
|
185
185
|
@twitter.insert(:Statuses, key + "3", {'body' => '3'})
|
186
186
|
@twitter.clear_column_family!(:Statuses)
|
187
|
-
assert_equal 0, @twitter.
|
187
|
+
assert_equal 0, @twitter.count_range(:Statuses)
|
188
188
|
end
|
189
189
|
|
190
190
|
def test_insert_key
|
@@ -193,7 +193,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
193
193
|
end
|
194
194
|
|
195
195
|
def test_insert_super_key
|
196
|
-
columns = {
|
196
|
+
columns = {@uuids[1] => 'v1', @uuids[2] => 'v2'}
|
197
197
|
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
198
198
|
assert_equal(columns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
|
199
199
|
end
|
@@ -204,7 +204,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
204
204
|
end
|
205
205
|
|
206
206
|
def test_get_column_values_super
|
207
|
-
user_columns, mentions_columns = {
|
207
|
+
user_columns, mentions_columns = {@uuids[1] => 'v1'}, {@uuids[2] => 'v2'}
|
208
208
|
@twitter.insert(:StatusRelationships, key,
|
209
209
|
{'user_timelines' => user_columns, 'mentions_timelines' => mentions_columns})
|
210
210
|
assert_equal [user_columns, mentions_columns],
|
@@ -225,8 +225,8 @@ class CassandraTest < Test::Unit::TestCase
|
|
225
225
|
# Not supported
|
226
226
|
# def test_get_columns_super_sub
|
227
227
|
# @twitter.insert(:StatusRelationships, key, {
|
228
|
-
# 'user_timelines' => {
|
229
|
-
# 'mentions_timelines' => {
|
228
|
+
# 'user_timelines' => {@uuids[1] => 'v1'},
|
229
|
+
# 'mentions_timelines' => {@uuids[2] => 'v2'}})
|
230
230
|
# assert_equal ['v1', 'v2'],
|
231
231
|
# @twitter.get_columns(:StatusRelationships, key, 'user_timelines', ['1', key])
|
232
232
|
# end
|
@@ -235,7 +235,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
235
235
|
@twitter.insert(:Statuses, key + "1", {'body' => '1'})
|
236
236
|
@twitter.insert(:Statuses, key + "2", {'body' => '2'})
|
237
237
|
@twitter.insert(:Statuses, key + "3", {'body' => '3'})
|
238
|
-
assert_equal 3, @twitter.
|
238
|
+
assert_equal 3, @twitter.count_range(:Statuses)
|
239
239
|
end
|
240
240
|
|
241
241
|
def test_count_columns
|
@@ -245,13 +245,13 @@ class CassandraTest < Test::Unit::TestCase
|
|
245
245
|
|
246
246
|
def test_count_super_columns
|
247
247
|
@twitter.insert(:StatusRelationships, key, {
|
248
|
-
'user_timelines' => {
|
249
|
-
'mentions_timelines' => {
|
248
|
+
'user_timelines' => {@uuids[1] => 'v1'},
|
249
|
+
'mentions_timelines' => {@uuids[2] => 'v2'}})
|
250
250
|
assert_equal 2, @twitter.count_columns(:StatusRelationships, key)
|
251
251
|
end
|
252
252
|
|
253
253
|
def test_count_super_sub_columns
|
254
|
-
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {
|
254
|
+
@twitter.insert(:StatusRelationships, key, {'user_timelines' => {@uuids[1] => 'v1', @uuids[2] => 'v2'}})
|
255
255
|
assert_equal 2, @twitter.count_columns(:StatusRelationships, key, 'user_timelines')
|
256
256
|
end
|
257
257
|
|