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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23762bc97b24f059702d33a82198651dc12a5849
4
- data.tar.gz: e5bdeca74f220ad8ade8f35a20b3751efd256eec
3
+ metadata.gz: 3b6090a71669ad2ce1765f4df908af55554ad3c2
4
+ data.tar.gz: bc7618330745f2d61d1e50c06514ef509fd68591
5
5
  SHA512:
6
- metadata.gz: ffff8841ff8da649d139ddc24d54c0a28bbba823fbe25ec7a00cde71a3685bc33e2ac92b1973a09208f419ef0660a03a2ae840dc008bd4af57ed3f8120399a39
7
- data.tar.gz: 88af7c90d6177d05afaf0d37f0eee2ecc563dd4ea9a48e3195d587dad18e88768f5f40389be12eedac86554de24c507cca1f14af4f9a33711feb4d79cf301312
6
+ metadata.gz: 693a6518ae0b0a296e45c6f1e1f52561b2fb8523b0ba0862b19c5efa4dd8bc2e697311e79046a044a5a893578a873f62c8420bd8457616e9031165ca811669a2
7
+ data.tar.gz: 2562aaf301fe5b205952ec04205657d39c76f1d8f0be22860f7c90b08e850f6d4d9894533f8424b8eaca1aa446a09445855e0f39dade50fff4a545f06402214f
@@ -54,4 +54,7 @@ module CassandraObject
54
54
  end
55
55
  end
56
56
 
57
+ require 'cassandra_object/custom_comparable'
58
+ require 'cassandra_object/composite'
59
+ require 'cassandra_object/long'
57
60
  require 'cassandra_object/railtie'
@@ -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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'sessionm-cassandra_object'
5
- s.version = '4.0.28'
5
+ s.version = '4.0.29'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
 
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.28
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