forked from cassandra-rb/cassandra
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cassandra-rb#115 from nearbuy/composite_columns
Initial support for composite column names
- Loading branch information
Showing
10 changed files
with
224 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
|
||
class Cassandra | ||
class Composite | ||
include ::Comparable | ||
attr_reader :parts | ||
attr_reader :column_slice | ||
|
||
def initialize(*parts) | ||
options = {} | ||
if parts.last.is_a?(Hash) | ||
options = parts.pop | ||
end | ||
@column_slice = options[:slice] | ||
raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice) | ||
|
||
if parts.length == 1 && parts[0].instance_of?(self.class) | ||
@column_slice = parts[0].column_slice | ||
@parts = parts[0].parts | ||
elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && valid_packed_composite?(parts[0]) | ||
unpack(parts[0]) | ||
else | ||
@parts = parts | ||
end | ||
end | ||
|
||
def [](*args) | ||
return @parts[*args] | ||
end | ||
|
||
def pack | ||
packed = @parts.map do |part| | ||
[part.length].pack('n') + part + "\x00" | ||
end | ||
if @column_slice | ||
part = @parts[-1] | ||
packed[-1] = [part.length].pack('n') + part + slice_end_of_component | ||
end | ||
return packed.join('') | ||
end | ||
|
||
def to_s | ||
return pack | ||
end | ||
|
||
def <=>(other) | ||
if !other.instance_of?(self.class) | ||
return @parts.first <=> other | ||
end | ||
eoc = slice_end_of_component.unpack('c')[0] | ||
other_eoc = other.slice_end_of_component.unpack('c')[0] | ||
@parts.zip(other.parts).each do |a, b| | ||
next if a == b | ||
if a.nil? && b.nil? | ||
return eoc <=> other_eoc | ||
end | ||
|
||
if a.nil? | ||
return @column_slice == :after ? 1 : -1 | ||
end | ||
if b.nil? | ||
return other.column_slice == :after ? -1 : 1 | ||
end | ||
return -1 if a < b | ||
return 1 if a > b | ||
end | ||
return 0 | ||
end | ||
|
||
def inspect | ||
return "#<Composite:#{@column_slice} #{@parts.inspect}>" | ||
end | ||
|
||
def slice_end_of_component | ||
return "\x01" if @column_slice == :after | ||
return "\xFF" if @column_slice == :before | ||
return "\x00" | ||
end | ||
|
||
private | ||
def unpack(packed_string) | ||
parts = [] | ||
end_of_component = nil | ||
while packed_string.length > 0 | ||
length = packed_string.slice(0, 2).unpack('n')[0] | ||
parts << packed_string.slice(2, length) | ||
end_of_component = packed_string.slice(2 + length, 1) | ||
|
||
packed_string = packed_string.slice(3 + length, packed_string.length) | ||
end | ||
@column_slice = :after if end_of_component == "\x01" | ||
@column_slice = :before if end_of_component == "\xFF" | ||
@parts = parts | ||
end | ||
|
||
def valid_packed_composite?(packed_string) | ||
while packed_string.length > 0 | ||
length = packed_string.slice(0, 2).unpack('n')[0] | ||
return false if length.nil? || length + 3 > packed_string.length | ||
|
||
end_of_component = packed_string.slice(2 + length, 1) | ||
if length + 3 != packed_string.length | ||
return false if end_of_component != "\x00" | ||
end | ||
|
||
packed_string = packed_string.slice(3 + length, packed_string.length) | ||
end | ||
return true | ||
end | ||
|
||
def hash | ||
return to_s.hash | ||
end | ||
|
||
def eql?(other) | ||
return to_s == other.to_s | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
require File.expand_path(File.dirname(__FILE__) + '/test_helper') | ||
|
||
class CompositeTypesTest < Test::Unit::TestCase | ||
include Cassandra::Constants | ||
|
||
def setup | ||
@col_parts = [[363].pack('N'), 'extradites-mulling', SimpleUUID::UUID.new().bytes] | ||
@col = Cassandra::Composite.new(*@col_parts) | ||
end | ||
|
||
def test_creation_from_parts | ||
assert_equal(@col_parts[0], @col[0]) | ||
assert_equal(@col_parts[1], @col[1]) | ||
assert_equal(@col_parts[2], @col[2]) | ||
end | ||
|
||
def test_packing_and_unpacking | ||
part0_length = 2 + 4 + 1 # size + int + end_term | ||
part1_length = 2 + @col_parts[1].length + 1 # size + string_len + end_term | ||
part2_length = 2 + @col_parts[2].length + 1 # size + uuid_bytes + end_term | ||
assert_equal(part0_length + part1_length + part2_length, @col.pack.length) | ||
|
||
col2 = Cassandra::Composite.new(@col.pack) | ||
assert_equal(@col_parts[0], col2[0]) | ||
assert_equal(@col_parts[1], col2[1]) | ||
assert_equal(@col_parts[2], col2[2]) | ||
assert_equal(@col, col2) | ||
end | ||
end |