mcmire-cassandra 0.12.2 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # for production, you should probably set pattern to %c instead of %l.
18
+ # (%l is slower.)
19
+
20
+ # output messages into a rolling log file as well as stdout
21
+ log4j.rootLogger=INFO,stdout,R
22
+
23
+ # stdout
24
+ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
25
+ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
26
+ log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
27
+
28
+ # rolling log file
29
+ log4j.appender.R=org.apache.log4j.RollingFileAppender
30
+ log4j.appender.R.maxFileSize=20MB
31
+ log4j.appender.R.maxBackupIndex=50
32
+ log4j.appender.R.layout=org.apache.log4j.PatternLayout
33
+ log4j.appender.R.layout.ConversionPattern=%5p [%t] %d{ISO8601} %F (line %L) %m%n
34
+ # Edit the next line to point to your logs directory
35
+ log4j.appender.R.File=data/logs/system.log
36
+
37
+ # Application logging options
38
+ #log4j.logger.org.apache.cassandra=DEBUG
39
+ #log4j.logger.org.apache.cassandra.db=DEBUG
40
+ #log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG
@@ -0,0 +1,69 @@
1
+ {"Twitter":{
2
+ "Users":{
3
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
4
+ "column_type":"Standard"},
5
+ "UserAudits":{
6
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
7
+ "column_type":"Standard"},
8
+ "UserCounters":{
9
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
10
+ "column_type":"Standard",
11
+ "default_validation_class":"CounterColumnType"},
12
+ "UserCounterAggregates":{
13
+ "subcomparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
14
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
15
+ "column_type":"Super",
16
+ "default_validation_class":"CounterColumnType"},
17
+ "UserRelationships":{
18
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
19
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
20
+ "column_type":"Super"},
21
+ "Usernames":{
22
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
23
+ "column_type":"Standard"},
24
+ "Statuses":{
25
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
26
+ "column_type":"Standard"},
27
+ "StatusAudits":{
28
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
29
+ "column_type":"Standard"},
30
+ "StatusRelationships":{
31
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
32
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
33
+ "column_type":"Super"},
34
+ "Indexes":{
35
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
36
+ "column_type":"Super"},
37
+ "TimelinishThings":{
38
+ "comparator_type":"org.apache.cassandra.db.marshal.BytesType",
39
+ "column_type":"Standard"}
40
+ },
41
+ "Multiblog":{
42
+ "Blogs":{
43
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
44
+ "column_type":"Standard"},
45
+ "Comments":{
46
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
47
+ "column_type":"Standard"}
48
+ },
49
+ "MultiblogLong":{
50
+ "Blogs":{
51
+ "comparator_type":"org.apache.cassandra.db.marshal.LongType",
52
+ "column_type":"Standard"},
53
+ "Comments":{
54
+ "comparator_type":"org.apache.cassandra.db.marshal.LongType",
55
+ "column_type":"Standard"}
56
+ },
57
+ "TypeConversions":{
58
+ "UUIDColumnConversion":{
59
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
60
+ "column_type":"Standard"},
61
+ "SuperUUID":{
62
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
63
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
64
+ "column_type":"Super"},
65
+ "CompositeColumnConversion":{
66
+ "comparator_type":"org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.IntegerType,org.apache.cassandra.db.marshal.UTF8Type)",
67
+ "column_type":"Standard"}
68
+ }
69
+ }
@@ -0,0 +1,51 @@
1
+ create keyspace Twitter with
2
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
3
+ strategy_options = {replication_factor:1};
4
+ use Twitter;
5
+ create column family Users with comparator = 'UTF8Type';
6
+ create column family UserAudits with comparator = 'UTF8Type';
7
+ create column family UserCounters with comparator = 'UTF8Type' and
8
+ default_validation_class = CounterColumnType;
9
+ create column family UserCounterAggregates with column_type = 'Super'
10
+ and comparator = 'UTF8Type' and
11
+ subcomparator = 'UTF8Type' and
12
+ default_validation_class = CounterColumnType;
13
+ create column family UserRelationships with
14
+ comparator = 'UTF8Type' and
15
+ column_type = 'Super' and
16
+ subcomparator = 'TimeUUIDType';
17
+ create column family Usernames with comparator = 'UTF8Type';
18
+ create column family Statuses with comparator = 'UTF8Type';
19
+ create column family StatusAudits with comparator = 'UTF8Type';
20
+ create column family StatusRelationships with
21
+ comparator = 'UTF8Type' and
22
+ column_type = 'Super' and
23
+ subcomparator = 'TimeUUIDType';
24
+ create column family Indexes with
25
+ comparator = 'UTF8Type' and
26
+ column_type = 'Super';
27
+ create column family TimelinishThings with
28
+ comparator = 'BytesType';
29
+
30
+ create keyspace Multiblog with
31
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
32
+ strategy_options = {replication_factor:1};
33
+ use Multiblog;
34
+ create column family Blogs with comparator = 'TimeUUIDType';
35
+ create column family Comments with comparator = 'TimeUUIDType';
36
+
37
+
38
+ create keyspace MultiblogLong with
39
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
40
+ strategy_options = {replication_factor:1};
41
+ use MultiblogLong;
42
+ create column family Blogs with comparator = 'LongType';
43
+ create column family Comments with comparator = 'LongType';
44
+
45
+ create keyspace TypeConversions with
46
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
47
+ strategy_options = {replication_factor:1};
48
+ use TypeConversions;
49
+ create column family UUIDColumnConversion with comparator = TimeUUIDType;
50
+ create column family SuperUUID with comparator = TimeUUIDType and column_type = Super;
51
+ create column family CompositeColumnConversion with comparator = 'CompositeType(IntegerType, UTF8Type)';
@@ -23,6 +23,7 @@ require 'cassandra/array'
23
23
  require 'cassandra/time'
24
24
  require 'cassandra/comparable'
25
25
  require 'cassandra/long'
26
+ require 'cassandra/composite'
26
27
  require 'cassandra/ordered_hash'
27
28
  require 'cassandra/columns'
28
29
  require 'cassandra/protocol'
@@ -0,0 +1,7 @@
1
+ class Cassandra
2
+ def self.VERSION
3
+ "1.0"
4
+ end
5
+ end
6
+
7
+ require "#{File.expand_path(File.dirname(__FILE__))}/../cassandra"
@@ -0,0 +1,10 @@
1
+ class Cassandra
2
+
3
+ ## Counters
4
+
5
+ # Add a value to the counter in cf:key:super column:column
6
+ def add(column_family, key, value, *columns_and_options)
7
+ column_family, column, sub_column, options = extract_and_validate_params(column_family, key, columns_and_options, WRITE_DEFAULTS)
8
+ _add(column_family, key, column, sub_column, value, options[:consistency])
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ class Cassandra
2
+ module Columns #:nodoc:
3
+ end
4
+ end
@@ -0,0 +1,23 @@
1
+ require "#{File.expand_path(File.dirname(__FILE__))}/../0.7/protocol"
2
+
3
+ class Cassandra
4
+ # Inner methods for actually doing the Thrift calls
5
+ module Protocol #:nodoc:
6
+ private
7
+
8
+ def _remove_counter(key, column_path, consistency_level)
9
+ client.remove_counter(key, column_path, consistency_level)
10
+ end
11
+
12
+ def _add(column_family, key, column, sub_column, value, consistency)
13
+ if is_super(column_family)
14
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => column)
15
+ counter_column = CassandraThrift::CounterColumn.new(:name => sub_column, :value => value)
16
+ else
17
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
18
+ counter_column = CassandraThrift::CounterColumn.new(:name => column, :value => value)
19
+ end
20
+ client.add(key, column_parent, counter_column, consistency)
21
+ end
22
+ end
23
+ end
@@ -18,10 +18,11 @@ class Cassandra
18
18
 
19
19
  def column_name_class_for_key(column_family, comparator_key)
20
20
  property = column_family_property(column_family, comparator_key)
21
- property =~ /.*\.(.*?)$/
21
+ property =~ /[^(]*\.(.*?)$/
22
22
  case $1
23
23
  when "LongType" then Long
24
24
  when "LexicalUUIDType", "TimeUUIDType" then SimpleUUID::UUID
25
+ when /^CompositeType\(/ then Composite
25
26
  else
26
27
  String # UTF8, Ascii, Bytes, anything else
27
28
  end
@@ -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
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "mcmire-cassandra"
5
- s.version = "0.12.2"
5
+ s.version = "0.12.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0.8") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Weaver, Ryan King"]
9
- s.date = "2012-03-29"
9
+ s.date = "2012-05-08"
10
10
  s.description = "A Ruby client for the Cassandra distributed database."
11
11
  s.email = ""
12
12
  s.executables = ["cassandra_helper"]
13
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
14
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "bin/cassandra_helper", "conf/0.6/cassandra.in.sh", "conf/0.6/log4j.properties", "conf/0.6/schema.json", "conf/0.6/storage-conf.xml", "conf/0.7/cassandra.in.sh", "conf/0.7/cassandra.yaml", "conf/0.7/log4j-server.properties", "conf/0.7/schema.json", "conf/0.7/schema.txt", "conf/0.8/cassandra.in.sh", "conf/0.8/cassandra.yaml", "conf/0.8/log4j-server.properties", "conf/0.8/schema.json", "conf/0.8/schema.txt", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/0.6/gen-rb/cassandra.rb", "vendor/0.6/gen-rb/cassandra_constants.rb", "vendor/0.6/gen-rb/cassandra_types.rb", "vendor/0.7/gen-rb/cassandra.rb", "vendor/0.7/gen-rb/cassandra_constants.rb", "vendor/0.7/gen-rb/cassandra_types.rb", "vendor/0.8/gen-rb/cassandra.rb", "vendor/0.8/gen-rb/cassandra_constants.rb", "vendor/0.8/gen-rb/cassandra_types.rb", "mcmire-cassandra.gemspec"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/1.0.rb", "lib/cassandra/1.0/cassandra.rb", "lib/cassandra/1.0/columns.rb", "lib/cassandra/1.0/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/composite.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
14
+ s.files = ["CHANGELOG", "Gemfile", "LICENSE", "Manifest", "README.md", "Rakefile", "bin/cassandra_helper", "conf/0.6/cassandra.in.sh", "conf/0.6/log4j.properties", "conf/0.6/schema.json", "conf/0.6/storage-conf.xml", "conf/0.7/cassandra.in.sh", "conf/0.7/cassandra.yaml", "conf/0.7/log4j-server.properties", "conf/0.7/schema.json", "conf/0.7/schema.txt", "conf/0.8/cassandra.in.sh", "conf/0.8/cassandra.yaml", "conf/0.8/log4j-server.properties", "conf/0.8/schema.json", "conf/0.8/schema.txt", "conf/1.0/cassandra.in.sh", "conf/1.0/cassandra.yaml", "conf/1.0/log4j-server.properties", "conf/1.0/schema.json", "conf/1.0/schema.txt", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/1.0.rb", "lib/cassandra/1.0/cassandra.rb", "lib/cassandra/1.0/columns.rb", "lib/cassandra/1.0/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/composite.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "mcmire-cassandra.gemspec", "test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/composite_type_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/0.6/gen-rb/cassandra.rb", "vendor/0.6/gen-rb/cassandra_constants.rb", "vendor/0.6/gen-rb/cassandra_types.rb", "vendor/0.7/gen-rb/cassandra.rb", "vendor/0.7/gen-rb/cassandra_constants.rb", "vendor/0.7/gen-rb/cassandra_types.rb", "vendor/0.8/gen-rb/cassandra.rb", "vendor/0.8/gen-rb/cassandra_constants.rb", "vendor/0.8/gen-rb/cassandra_types.rb", "vendor/1.0/gen-rb/cassandra.rb", "vendor/1.0/gen-rb/cassandra_constants.rb", "vendor/1.0/gen-rb/cassandra_types.rb"]
15
15
  s.homepage = "http://fauna.github.com/fauna/mcmire-cassandra/"
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mcmire-cassandra", "--main", "README.md"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = "fauna"
19
19
  s.rubygems_version = "1.8.11"
20
20
  s.summary = "A Ruby client for the Cassandra distributed database."
21
- s.test_files = ["test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb"]
21
+ s.test_files = ["test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/composite_type_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  s.specification_version = 3
@@ -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
@@ -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)
@@ -501,12 +507,12 @@ class CassandraTest < Test::Unit::TestCase
501
507
 
502
508
  def test_count_columns
503
509
  columns = (1..200).inject(Hash.new){|h,v| h['column' + v.to_s] = v.to_s; h;}
504
-
510
+
505
511
  @twitter.insert(:Statuses, key, columns)
506
512
  assert_equal 200, @twitter.count_columns(:Statuses, key, :count => 200)
507
- assert_equal 100, @twitter.count_columns(:Statuses, key)
513
+ assert_equal 100, @twitter.count_columns(:Statuses, key)
508
514
  assert_equal 55, @twitter.count_columns(:Statuses, key, :count => 55)
509
-
515
+
510
516
  end
511
517
 
512
518
  def test_count_super_columns
@@ -556,24 +562,24 @@ class CassandraTest < Test::Unit::TestCase
556
562
  assert_equal({}, @twitter.get(:Users, k + '2')) # Not yet written
557
563
  assert_equal({}, @twitter.get(:Statuses, k + '3')) # Not yet written
558
564
 
559
- @twitter.remove(:Users, k + '1') # Full row
565
+ @twitter.remove(:Users, k + '1') # Full row
560
566
  assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Not yet removed
561
567
 
562
568
  @twitter.remove(:Users, k + '0', 'delete_me') # A single column of the row
563
569
  assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Not yet removed
564
-
570
+
565
571
  @twitter.remove(:Users, k + '4')
566
572
  @twitter.insert(:Users, k + '4', {'body' => 'v4', 'user' => 'v4'})
567
573
  assert_equal({}, @twitter.get(:Users, k + '4')) # Not yet written
568
574
 
569
575
  # SuperColumns
570
576
  # Add and delete new sub columns to the user timeline supercolumn
571
- @twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
577
+ @twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
572
578
  @twitter.remove(:StatusRelationships, k, 'user_timelines' , subcolumn_to_delete ) # Delete the first of the initial_subcolumns from the user_timeline supercolumn
573
579
  assert_equal(initial_subcolumns, @twitter.get(:StatusRelationships, k, 'user_timelines')) # No additions or deletes reflected yet
574
- # Delete a complete supercolumn
580
+ # Delete a complete supercolumn
575
581
  @twitter.remove(:StatusRelationships, k, 'dummy_supercolumn' ) # Delete the full dummy supercolumn
576
- assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
582
+ assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
577
583
  end
578
584
 
579
585
  assert_equal({'body' => 'v2', 'user' => 'v2'}, @twitter.get(:Users, k + '2')) # Written
@@ -581,9 +587,9 @@ class CassandraTest < Test::Unit::TestCase
581
587
  assert_equal({'body' => 'v4', 'user' => 'v4'}, @twitter.get(:Users, k + '4')) # Written
582
588
  assert_equal({'body' => 'v'}, @twitter.get(:Statuses, k + '3')) # Written
583
589
  assert_equal({}, @twitter.get(:Users, k + '1')) # Removed
584
-
590
+
585
591
  assert_equal({ 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # 'delete_me' column removed
586
-
592
+
587
593
 
588
594
  assert_equal({'body' => 'v2', 'user' => 'v2'}.keys.sort, @twitter.get(:Users, k + '2').timestamps.keys.sort) # Written
589
595
  assert_equal({'body' => 'v3', 'user' => 'v3', 'location' => 'v3'}.keys.sort, @twitter.get(:Users, k + '3').timestamps.keys.sort) # Written and compacted
@@ -593,7 +599,7 @@ class CassandraTest < Test::Unit::TestCase
593
599
  # Final result: initial_subcolumns - initial_subcolumns.first + new_subcolumns
594
600
  resulting_subcolumns = initial_subcolumns.merge(new_subcolumns).reject{|k2,v| k2 == subcolumn_to_delete }
595
601
  assert_equal(resulting_subcolumns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
596
- assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
602
+ assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
597
603
 
598
604
  end
599
605
 
@@ -834,8 +840,47 @@ class CassandraTest < Test::Unit::TestCase
834
840
  assert_equal(1, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'today'))
835
841
  assert_equal(2, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'tomorrow'))
836
842
  end
843
+
844
+ def test_composite_column_type_conversion
845
+ columns = {}
846
+ @composites.each_with_index do |c, index|
847
+ columns[c] = "value-#{index}"
848
+ end
849
+ @type_conversions.insert(:CompositeColumnConversion, key, columns)
850
+ columns_in_order = [
851
+ Cassandra::Composite.new([1].pack('N'), "elephant"),
852
+ Cassandra::Composite.new([5].pack('N'), "aardvark"),
853
+ Cassandra::Composite.new([5].pack('N'), "zebra"),
854
+ Cassandra::Composite.new([10].pack('N'), "kangaroo"),
855
+ ]
856
+ assert_equal(columns_in_order, @type_conversions.get(:CompositeColumnConversion, key).keys)
857
+
858
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
859
+ :start => Cassandra::Composite.new([1].pack('N')),
860
+ :finish => Cassandra::Composite.new([10].pack('N')),
861
+ ).keys
862
+ assert_equal(columns_in_order[0..-2], column_slice)
863
+
864
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
865
+ :start => Cassandra::Composite.new([5].pack('N')),
866
+ :finish => Cassandra::Composite.new([5].pack('N'), :slice => :after),
867
+ ).keys
868
+ assert_equal(columns_in_order[1..2], column_slice)
869
+
870
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
871
+ :start => Cassandra::Composite.new([5].pack('N'), :slice => :after).to_s,
872
+ ).keys
873
+ assert_equal([columns_in_order[-1]], column_slice)
874
+
875
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
876
+ :finish => Cassandra::Composite.new([10].pack('N'), :slice => :before).to_s,
877
+ ).keys
878
+ assert_equal(columns_in_order[0..-2], column_slice)
879
+
880
+ assert_equal('value-2', @type_conversions.get(:CompositeColumnConversion, key, columns_in_order.first))
881
+ end
837
882
  end
838
-
883
+
839
884
  def test_column_timestamps
840
885
  base_time = Time.now
841
886
  @twitter.insert(:Statuses, "time-key", { "body" => "value" })