sessionm-cassandra_object 4.0.28 → 4.0.29
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.
- checksums.yaml +4 -4
- data/lib/cassandra_object.rb +3 -0
- data/lib/cassandra_object/composite.rb +140 -0
- data/lib/cassandra_object/custom_comparable.rb +28 -0
- data/lib/cassandra_object/long.rb +58 -0
- data/sessionm-cassandra_object.gemspec +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b6090a71669ad2ce1765f4df908af55554ad3c2
|
4
|
+
data.tar.gz: bc7618330745f2d61d1e50c06514ef509fd68591
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 693a6518ae0b0a296e45c6f1e1f52561b2fb8523b0ba0862b19c5efa4dd8bc2e697311e79046a044a5a893578a873f62c8420bd8457616e9031165ca811669a2
|
7
|
+
data.tar.gz: 2562aaf301fe5b205952ec04205657d39c76f1d8f0be22860f7c90b08e850f6d4d9894533f8424b8eaca1aa446a09445855e0f39dade50fff4a545f06402214f
|
data/lib/cassandra_object.rb
CHANGED
@@ -0,0 +1,140 @@
|
|
1
|
+
class Cassandra
|
2
|
+
class Composite
|
3
|
+
include ::Comparable
|
4
|
+
attr_reader :parts
|
5
|
+
attr_reader :column_slice
|
6
|
+
|
7
|
+
def initialize(*parts)
|
8
|
+
return if parts.empty?
|
9
|
+
|
10
|
+
options = {}
|
11
|
+
if parts.last.is_a?(Hash)
|
12
|
+
options = parts.pop
|
13
|
+
end
|
14
|
+
@column_slice = options[:slice]
|
15
|
+
raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice)
|
16
|
+
|
17
|
+
if parts.length == 1 && parts[0].instance_of?(self.class)
|
18
|
+
@column_slice = parts[0].column_slice
|
19
|
+
@parts = parts[0].parts
|
20
|
+
elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && try_packed_composite(parts[0])
|
21
|
+
@hash = parts[0].hash
|
22
|
+
else
|
23
|
+
@parts = parts
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.new_from_packed(packed)
|
28
|
+
obj = new
|
29
|
+
obj.fast_unpack(packed)
|
30
|
+
return obj
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](*args)
|
34
|
+
return @parts[*args]
|
35
|
+
end
|
36
|
+
|
37
|
+
def pack
|
38
|
+
packed = @parts.map do |part|
|
39
|
+
[part.length].pack('n') + part + "\x00"
|
40
|
+
end
|
41
|
+
if @column_slice
|
42
|
+
part = @parts[-1]
|
43
|
+
packed[-1] = [part.length].pack('n') + part + slice_end_of_component
|
44
|
+
end
|
45
|
+
return packed.join('')
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
return pack
|
50
|
+
end
|
51
|
+
|
52
|
+
def <=>(other)
|
53
|
+
if !other.instance_of?(self.class)
|
54
|
+
return @parts.first <=> other
|
55
|
+
end
|
56
|
+
eoc = slice_end_of_component.unpack('c')[0]
|
57
|
+
other_eoc = other.slice_end_of_component.unpack('c')[0]
|
58
|
+
@parts.zip(other.parts).each do |a, b|
|
59
|
+
next if a == b
|
60
|
+
if a.nil? && b.nil?
|
61
|
+
return eoc <=> other_eoc
|
62
|
+
end
|
63
|
+
|
64
|
+
if a.nil?
|
65
|
+
return @column_slice == :after ? 1 : -1
|
66
|
+
end
|
67
|
+
if b.nil?
|
68
|
+
return other.column_slice == :after ? -1 : 1
|
69
|
+
end
|
70
|
+
return -1 if a < b
|
71
|
+
return 1 if a > b
|
72
|
+
end
|
73
|
+
return 0
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
return "#<#{self.class}:#{@column_slice} #{@parts.inspect}>"
|
78
|
+
end
|
79
|
+
|
80
|
+
def slice_end_of_component
|
81
|
+
return "\x01" if @column_slice == :after
|
82
|
+
return "\xFF" if @column_slice == :before
|
83
|
+
return "\x00"
|
84
|
+
end
|
85
|
+
|
86
|
+
def fast_unpack(packed_string)
|
87
|
+
@hash = packed_string.hash
|
88
|
+
|
89
|
+
@parts = []
|
90
|
+
end_of_component = packed_string.slice(packed_string.length-1, 1)
|
91
|
+
while packed_string.length > 0
|
92
|
+
length = packed_string.unpack('n')[0]
|
93
|
+
@parts << packed_string.slice(2, length)
|
94
|
+
|
95
|
+
packed_string.slice!(0, length+3)
|
96
|
+
end
|
97
|
+
|
98
|
+
@column_slice = :after if end_of_component == "\x01"
|
99
|
+
@column_slice = :before if end_of_component == "\xFF"
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def try_packed_composite(packed_string)
|
104
|
+
parts = []
|
105
|
+
end_of_component = nil
|
106
|
+
while packed_string.length > 0
|
107
|
+
length = packed_string.slice(0, 2).unpack('n')[0]
|
108
|
+
return false if length.nil? || length + 3 > packed_string.length
|
109
|
+
|
110
|
+
parts << packed_string.slice(2, length)
|
111
|
+
end_of_component = packed_string.slice(2 + length, 1)
|
112
|
+
if length + 3 != packed_string.length
|
113
|
+
return false if end_of_component != "\x00"
|
114
|
+
end
|
115
|
+
|
116
|
+
packed_string = packed_string.slice(3 + length, packed_string.length)
|
117
|
+
end
|
118
|
+
|
119
|
+
@column_slice = :after if end_of_component == "\x01"
|
120
|
+
@column_slice = :before if end_of_component == "\xFF"
|
121
|
+
@parts = parts
|
122
|
+
|
123
|
+
return true
|
124
|
+
end
|
125
|
+
|
126
|
+
def hash
|
127
|
+
return @hash ||= pack.hash
|
128
|
+
end
|
129
|
+
|
130
|
+
def eql?(other)
|
131
|
+
return to_s == other.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
begin
|
137
|
+
require "cassandra_native"
|
138
|
+
rescue LoadError
|
139
|
+
puts "Unable to load cassandra_native extension. Defaulting to pure Ruby libraries."
|
140
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
class Cassandra
|
3
|
+
# Abstract base class for comparable numeric column name types
|
4
|
+
class CustomComparable
|
5
|
+
class TypeError < ::TypeError #:nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
def <=>(other)
|
9
|
+
self.to_i <=> other.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def hash
|
13
|
+
@bytes.hash
|
14
|
+
end
|
15
|
+
|
16
|
+
def eql?(other)
|
17
|
+
other.is_a?(Comparable) and @bytes == other.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
other.respond_to?(:to_i) && self.to_i == other.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@bytes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
class Cassandra
|
3
|
+
# A temporally-ordered Long class for use in Cassandra column names
|
4
|
+
class Long < CustomComparable
|
5
|
+
|
6
|
+
# FIXME Should unify with or subclass Cassandra::UUID
|
7
|
+
def initialize(bytes = nil)
|
8
|
+
case bytes
|
9
|
+
when self.class # Long
|
10
|
+
@bytes = bytes.to_s
|
11
|
+
when String
|
12
|
+
case bytes.size
|
13
|
+
when 8 # Raw byte array
|
14
|
+
@bytes = bytes
|
15
|
+
when 18 # Human-readable UUID-like representation; inverse of #to_guid
|
16
|
+
elements = bytes.split("-")
|
17
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (malformed UUID-like representation)" if elements.size != 3
|
18
|
+
@bytes = [elements.join].pack('H32')
|
19
|
+
else
|
20
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (invalid bytecount)"
|
21
|
+
end
|
22
|
+
when Integer
|
23
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (integer out of range)" if bytes < 0 or bytes > 2**64
|
24
|
+
@bytes = [bytes >> 32, bytes % 2**32].pack("NN")
|
25
|
+
when NilClass, Time
|
26
|
+
# Time.stamp is 52 bytes, so we have 12 bytes of entropy left over
|
27
|
+
int = ((bytes || Time).stamp << 12) + rand(2**12)
|
28
|
+
@bytes = [int >> 32, int % 2**32].pack("NN")
|
29
|
+
else
|
30
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (unknown source class)"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_i
|
35
|
+
@to_i ||= begin
|
36
|
+
ints = @bytes.unpack("NN")
|
37
|
+
(ints[0] << 32) +
|
38
|
+
ints[1]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_guid
|
43
|
+
"%08x-%04x-%04x" % @bytes.unpack("Nnn")
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"<Cassandra::Long##{object_id} time: #{
|
48
|
+
Time.at((to_i >> 12) / 1_000_000).utc.inspect
|
49
|
+
}, usecs: #{
|
50
|
+
(to_i >> 12) % 1_000_000
|
51
|
+
}, jitter: #{
|
52
|
+
to_i % 2**12
|
53
|
+
}, guid: #{
|
54
|
+
to_guid
|
55
|
+
}>"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sessionm-cassandra_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.29
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doug Youch
|
@@ -44,10 +44,12 @@ files:
|
|
44
44
|
- lib/cassandra_object/batches.rb
|
45
45
|
- lib/cassandra_object/callbacks.rb
|
46
46
|
- lib/cassandra_object/collection.rb
|
47
|
+
- lib/cassandra_object/composite.rb
|
47
48
|
- lib/cassandra_object/configuration.rb
|
48
49
|
- lib/cassandra_object/connection.rb
|
49
50
|
- lib/cassandra_object/consistency.rb
|
50
51
|
- lib/cassandra_object/cursor.rb
|
52
|
+
- lib/cassandra_object/custom_comparable.rb
|
51
53
|
- lib/cassandra_object/dirty.rb
|
52
54
|
- lib/cassandra_object/errors.rb
|
53
55
|
- lib/cassandra_object/finder_methods.rb
|
@@ -61,6 +63,7 @@ files:
|
|
61
63
|
- lib/cassandra_object/identity/natural_key_factory.rb
|
62
64
|
- lib/cassandra_object/identity/uuid_key_factory.rb
|
63
65
|
- lib/cassandra_object/log_subscriber.rb
|
66
|
+
- lib/cassandra_object/long.rb
|
64
67
|
- lib/cassandra_object/migrations.rb
|
65
68
|
- lib/cassandra_object/migrations/migration.rb
|
66
69
|
- lib/cassandra_object/mocking.rb
|