cassilds 0.9.2 → 0.12.1
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/CHANGELOG +51 -1
- data/LICENSE +0 -0
- data/Manifest +25 -7
- data/README.md +352 -0
- data/Rakefile +169 -1
- data/cassilds.gemspec +45 -0
- data/conf/{cassandra.in.sh → 0.6/cassandra.in.sh} +0 -0
- data/conf/{log4j.properties → 0.6/log4j.properties} +0 -0
- data/conf/0.6/schema.json +57 -0
- data/conf/{storage-conf.xml → 0.6/storage-conf.xml} +15 -5
- data/conf/0.7/cassandra.in.sh +46 -0
- data/conf/0.7/cassandra.yaml +336 -0
- data/conf/0.7/log4j-server.properties +41 -0
- data/conf/0.7/schema.json +57 -0
- data/conf/0.7/schema.txt +45 -0
- data/conf/0.8/cassandra.in.sh +41 -0
- data/conf/0.8/cassandra.yaml +61 -0
- data/conf/0.8/log4j-server.properties +40 -0
- data/conf/0.8/schema.json +66 -0
- data/conf/0.8/schema.txt +51 -0
- data/lib/cassandra/0.6/cassandra.rb +58 -13
- data/lib/cassandra/0.6/columns.rb +43 -0
- data/lib/cassandra/0.6/protocol.rb +16 -18
- data/lib/cassandra/0.6.rb +0 -0
- data/lib/cassandra/0.7/cassandra.rb +0 -270
- data/lib/cassandra/0.7/columns.rb +1 -64
- data/lib/cassandra/0.7/protocol.rb +0 -134
- data/lib/cassandra/0.7.rb +0 -0
- data/lib/cassandra/0.8/cassandra.rb +10 -0
- data/lib/cassandra/0.8/columns.rb +4 -0
- data/lib/cassandra/0.8/protocol.rb +23 -0
- data/lib/cassandra/0.8.rb +7 -0
- data/lib/cassandra/array.rb +0 -0
- data/lib/cassandra/cassandra.rb +877 -111
- data/lib/cassandra/{0.7/column_family.rb → column_family.rb} +0 -0
- data/lib/cassandra/columns.rb +72 -6
- data/lib/cassandra/comparable.rb +0 -0
- data/lib/cassandra/constants.rb +0 -0
- data/lib/cassandra/debug.rb +0 -0
- data/lib/cassandra/helpers.rb +1 -0
- data/lib/cassandra/{0.7/keyspace.rb → keyspace.rb} +0 -0
- data/lib/cassandra/long.rb +5 -0
- data/lib/cassandra/mock.rb +259 -85
- data/lib/cassandra/ordered_hash.rb +10 -18
- data/lib/cassandra/protocol.rb +120 -0
- data/lib/cassandra/time.rb +0 -0
- data/lib/cassandra.rb +6 -7
- data/test/cassandra_client_test.rb +0 -0
- data/test/cassandra_mock_test.rb +52 -28
- data/test/cassandra_test.rb +465 -44
- data/test/comparable_types_test.rb +0 -0
- data/test/eventmachine_test.rb +30 -30
- data/test/ordered_hash_test.rb +6 -0
- data/test/test_helper.rb +3 -2
- data/vendor/0.6/gen-rb/cassandra.rb +0 -0
- data/vendor/0.6/gen-rb/cassandra_constants.rb +0 -0
- data/vendor/0.6/gen-rb/cassandra_types.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra_constants.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra_types.rb +4 -2
- data/vendor/0.8/gen-rb/cassandra.rb +2215 -0
- data/vendor/0.8/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/0.8/gen-rb/cassandra_types.rb +816 -0
- metadata +50 -27
- data/README.rdoc +0 -83
- data/cassandra.gemspec +0 -46
- data/conf/cassandra.yaml +0 -113
File without changes
|
data/lib/cassandra/columns.rb
CHANGED
@@ -4,15 +4,15 @@ class Cassandra
|
|
4
4
|
module Columns #:nodoc:
|
5
5
|
|
6
6
|
def is_super(column_family)
|
7
|
-
@is_super[column_family] ||= column_family_property(column_family, '
|
7
|
+
@is_super[column_family] ||= column_family_property(column_family, 'column_type') == "Super"
|
8
8
|
end
|
9
9
|
|
10
10
|
def column_name_class(column_family)
|
11
|
-
@column_name_class[column_family] ||= column_name_class_for_key(column_family, "
|
11
|
+
@column_name_class[column_family] ||= column_name_class_for_key(column_family, "comparator_type")
|
12
12
|
end
|
13
13
|
|
14
14
|
def sub_column_name_class(column_family)
|
15
|
-
@sub_column_name_class[column_family] ||= column_name_class_for_key(column_family, "
|
15
|
+
@sub_column_name_class[column_family] ||= column_name_class_for_key(column_family, "subcomparator_type")
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
@@ -29,10 +29,20 @@ class Cassandra
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def column_family_property(column_family, key)
|
32
|
-
|
32
|
+
cfdef = schema.cf_defs.find {|cfdef| cfdef.name == column_family }
|
33
|
+
unless cfdef
|
33
34
|
raise AccessError, "Invalid column family \"#{column_family}\""
|
34
35
|
end
|
35
|
-
|
36
|
+
cfdef.send(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def multi_key_slices_to_hash(column_family, array, return_empty_rows = false)
|
40
|
+
ret = OrderedHash.new
|
41
|
+
array.each do |value|
|
42
|
+
next if return_empty_rows == false && value.columns.length == 0
|
43
|
+
ret[value.key] = columns_to_hash(column_family, value.columns)
|
44
|
+
end
|
45
|
+
ret
|
36
46
|
end
|
37
47
|
|
38
48
|
def multi_column_to_hash!(hash)
|
@@ -64,16 +74,72 @@ class Cassandra
|
|
64
74
|
def columns_to_hash_for_classes(columns, column_name_class, sub_column_name_class = nil)
|
65
75
|
hash = OrderedHash.new
|
66
76
|
Array(columns).each do |c|
|
67
|
-
c = c.super_column || c.column if c.is_a?(CassandraThrift::ColumnOrSuperColumn)
|
77
|
+
c = c.super_column || c.column || c.counter_column if c.is_a?(CassandraThrift::ColumnOrSuperColumn)
|
68
78
|
case c
|
69
79
|
when CassandraThrift::SuperColumn
|
70
80
|
hash.[]=(column_name_class.new(c.name), columns_to_hash_for_classes(c.columns, sub_column_name_class)) # Pop the class stack, and recurse
|
71
81
|
when CassandraThrift::Column
|
72
82
|
hash.[]=(column_name_class.new(c.name), c.value, c.timestamp)
|
83
|
+
when CassandraThrift::CounterColumn
|
84
|
+
hash.[]=(column_name_class.new(c.name), c.value, 0)
|
73
85
|
end
|
74
86
|
end
|
75
87
|
hash
|
76
88
|
end
|
77
89
|
|
90
|
+
def _standard_insert_mutation(column_family, column_name, value, timestamp, ttl = nil)
|
91
|
+
CassandraThrift::Mutation.new(
|
92
|
+
:column_or_supercolumn => CassandraThrift::ColumnOrSuperColumn.new(
|
93
|
+
:column => CassandraThrift::Column.new(
|
94
|
+
:name => column_name_class(column_family).new(column_name).to_s,
|
95
|
+
:value => value,
|
96
|
+
:timestamp => timestamp,
|
97
|
+
:ttl => ttl
|
98
|
+
)
|
99
|
+
)
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
def _super_insert_mutation(column_family, super_column_name, sub_columns, timestamp, ttl = nil)
|
104
|
+
CassandraThrift::Mutation.new(:column_or_supercolumn =>
|
105
|
+
CassandraThrift::ColumnOrSuperColumn.new(
|
106
|
+
:super_column => CassandraThrift::SuperColumn.new(
|
107
|
+
:name => column_name_class(column_family).new(super_column_name).to_s,
|
108
|
+
:columns => sub_columns.collect { |sub_column_name, sub_column_value|
|
109
|
+
CassandraThrift::Column.new(
|
110
|
+
:name => sub_column_name_class(column_family).new(sub_column_name).to_s,
|
111
|
+
:value => sub_column_value.to_s,
|
112
|
+
:timestamp => timestamp,
|
113
|
+
:ttl => ttl
|
114
|
+
)
|
115
|
+
}
|
116
|
+
)
|
117
|
+
)
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
# General info about a deletion object within a mutation
|
122
|
+
# timestamp - required. If this is the only param, it will cause deletion of the whole key at that TS
|
123
|
+
# supercolumn - opt. If passed, the deletes will only occur within that supercolumn (only subcolumns
|
124
|
+
# will be deleted). Otherwise the normal columns will be deleted.
|
125
|
+
# predicate - opt. Defines how to match the columns to delete. if supercolumn passed, the slice will
|
126
|
+
# be scoped to subcolumns of that supercolumn.
|
127
|
+
|
128
|
+
# Deletes a single column from the containing key/CF (and possibly supercolumn), at a given timestamp.
|
129
|
+
# Although mutations (as opposed to 'remove' calls) support deleting slices and lists of columns in one shot, this is not implemented here.
|
130
|
+
# The main reason being that the batch function takes removes, but removes don't have that capability...so we'd need to change the remove
|
131
|
+
# methods to use delete mutation calls...although that might have performance implications. We'll leave that refactoring for later.
|
132
|
+
def _delete_mutation(cf, column, subcolumn, timestamp, options={})
|
133
|
+
deletion_hash = {:timestamp => timestamp}
|
134
|
+
if is_super(cf)
|
135
|
+
deletion_hash[:super_column] = column if column
|
136
|
+
deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [subcolumn]) if subcolumn
|
137
|
+
else
|
138
|
+
deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [column]) if column
|
139
|
+
end
|
140
|
+
CassandraThrift::Mutation.new(
|
141
|
+
:deletion => CassandraThrift::Deletion.new(deletion_hash)
|
142
|
+
)
|
143
|
+
end
|
78
144
|
end
|
79
145
|
end
|
data/lib/cassandra/comparable.rb
CHANGED
File without changes
|
data/lib/cassandra/constants.rb
CHANGED
File without changes
|
data/lib/cassandra/debug.rb
CHANGED
File without changes
|
data/lib/cassandra/helpers.rb
CHANGED
@@ -17,6 +17,7 @@ class Cassandra
|
|
17
17
|
|
18
18
|
# Ranges
|
19
19
|
column, sub_column = args[0], args[1]
|
20
|
+
raise ArgumentError, "Invalid arguments: subcolumns specified for a non-supercolumn family" if sub_column && !is_super(column_family)
|
20
21
|
klass, sub_klass = column_name_class(column_family), sub_column_name_class(column_family)
|
21
22
|
range_class = column ? sub_klass : klass
|
22
23
|
|
File without changes
|
data/lib/cassandra/long.rb
CHANGED
data/lib/cassandra/mock.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
1
|
class SimpleUUID::UUID
|
4
2
|
def >=(other)
|
5
3
|
(self <=> other) >= 0
|
@@ -15,11 +13,15 @@ class Cassandra
|
|
15
13
|
include ::Cassandra::Helpers
|
16
14
|
include ::Cassandra::Columns
|
17
15
|
|
18
|
-
|
16
|
+
attr_reader :keyspace
|
17
|
+
|
18
|
+
def initialize(keyspace, schema)
|
19
|
+
@is_super = {}
|
19
20
|
@keyspace = keyspace
|
20
21
|
@column_name_class = {}
|
21
22
|
@sub_column_name_class = {}
|
22
|
-
@
|
23
|
+
@indexes = {}
|
24
|
+
@schema = schema[keyspace]
|
23
25
|
clear_keyspace!
|
24
26
|
end
|
25
27
|
|
@@ -34,12 +36,20 @@ class Cassandra
|
|
34
36
|
@data[column_family.to_sym] = OrderedHash.new
|
35
37
|
end
|
36
38
|
|
39
|
+
def default_write_consistency=(value)
|
40
|
+
WRITE_DEFAULTS[:consistency] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_read_consistency=(value)
|
44
|
+
READ_DEFAULTS[:consistency] = value
|
45
|
+
end
|
46
|
+
|
37
47
|
def insert(column_family, key, hash_or_array, options = {})
|
38
48
|
if @batch
|
39
49
|
@batch << [:insert, column_family, key, hash_or_array, options]
|
40
50
|
else
|
41
51
|
raise ArgumentError if key.nil?
|
42
|
-
if
|
52
|
+
if !is_super(column_family)
|
43
53
|
insert_standard(column_family, key, hash_or_array)
|
44
54
|
else
|
45
55
|
insert_super(column_family, key, hash_or_array)
|
@@ -77,7 +87,7 @@ class Cassandra
|
|
77
87
|
def get(column_family, key, *columns_and_options)
|
78
88
|
column_family, column, sub_column, options =
|
79
89
|
extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
|
80
|
-
if
|
90
|
+
if !is_super(column_family)
|
81
91
|
get_standard(column_family, key, column, options)
|
82
92
|
else
|
83
93
|
get_super(column_family, key, column, sub_column, options)
|
@@ -85,41 +95,44 @@ class Cassandra
|
|
85
95
|
end
|
86
96
|
|
87
97
|
def get_standard(column_family, key, column, options)
|
88
|
-
|
98
|
+
columns = cf(column_family)[key] || OrderedHash.new
|
99
|
+
row = columns_to_hash(column_family, columns)
|
100
|
+
|
89
101
|
if column
|
90
102
|
row[column]
|
91
103
|
else
|
92
104
|
row = apply_range(row, column_family, options[:start], options[:finish])
|
93
|
-
apply_count(row, options[:count], options[:reversed])
|
105
|
+
row = apply_count(row, options[:count], options[:reversed])
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
97
109
|
def get_super(column_family, key, column, sub_column, options)
|
110
|
+
columns = cf(column_family)[key] || OrderedHash.new
|
111
|
+
row = columns_to_hash(column_family, columns)
|
112
|
+
|
98
113
|
if column
|
99
114
|
if sub_column
|
100
|
-
if
|
101
|
-
|
102
|
-
|
103
|
-
cf(column_family)[key][column][sub_column]
|
115
|
+
if row[column] &&
|
116
|
+
row[column][sub_column]
|
117
|
+
row[column][sub_column]
|
104
118
|
else
|
105
119
|
nil
|
106
120
|
end
|
107
121
|
else
|
108
|
-
row =
|
109
|
-
cf(column_family)[key][column] :
|
110
|
-
OrderedHash.new
|
122
|
+
row = row[column] || OrderedHash.new
|
111
123
|
row = apply_range(row, column_family, options[:start], options[:finish], false)
|
112
|
-
apply_count(row, options[:count], options[:reversed])
|
124
|
+
row = apply_count(row, options[:count], options[:reversed])
|
113
125
|
end
|
114
|
-
elsif cf(column_family)[key]
|
115
|
-
cf(column_family)[key]
|
116
126
|
else
|
117
|
-
|
127
|
+
row
|
118
128
|
end
|
119
129
|
end
|
120
130
|
|
121
|
-
def exists?(column_family, key,
|
122
|
-
|
131
|
+
def exists?(column_family, key, *columns_and_options)
|
132
|
+
column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
|
133
|
+
results = get(column_family, key, column, sub_column)
|
134
|
+
|
135
|
+
![{}, nil].include?(results)
|
123
136
|
end
|
124
137
|
|
125
138
|
def multi_get(column_family, keys, *columns_and_options)
|
@@ -133,13 +146,13 @@ class Cassandra
|
|
133
146
|
def remove(column_family, key, *columns_and_options)
|
134
147
|
column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
|
135
148
|
if @batch
|
136
|
-
@batch << [:remove, column_family, key, column]
|
149
|
+
@batch << [:remove, column_family, key, column, sub_column]
|
137
150
|
else
|
138
151
|
if column
|
139
152
|
if sub_column
|
140
|
-
cf(column_family)[key][column].delete(sub_column)
|
153
|
+
cf(column_family)[key][column].delete(sub_column.to_s) if cf(column_family)[key][column]
|
141
154
|
else
|
142
|
-
cf(column_family)[key].delete(column)
|
155
|
+
cf(column_family)[key].delete(column.to_s) if cf(column_family)[key]
|
143
156
|
end
|
144
157
|
else
|
145
158
|
cf(column_family).delete(key)
|
@@ -151,7 +164,6 @@ class Cassandra
|
|
151
164
|
column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
|
152
165
|
d = get(column_family, key)
|
153
166
|
|
154
|
-
|
155
167
|
if sub_columns
|
156
168
|
sub_columns.collect do |sub_column|
|
157
169
|
d[columns][sub_column]
|
@@ -163,8 +175,10 @@ class Cassandra
|
|
163
175
|
end
|
164
176
|
end
|
165
177
|
|
166
|
-
def count_columns(column_family, key,
|
167
|
-
|
178
|
+
def count_columns(column_family, key, *columns_and_options)
|
179
|
+
column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
|
180
|
+
|
181
|
+
get(column_family, key, columns, options).keys.length
|
168
182
|
end
|
169
183
|
|
170
184
|
def multi_get_columns(column_family, keys, columns)
|
@@ -181,67 +195,217 @@ class Cassandra
|
|
181
195
|
end
|
182
196
|
end
|
183
197
|
|
184
|
-
def get_range(column_family, options = {})
|
185
|
-
column_family, _, _, options = extract_and_validate_params_for_real(column_family, "", [options],
|
186
|
-
|
198
|
+
def get_range(column_family, options = {}, &blk)
|
199
|
+
column_family, _, _, options = extract_and_validate_params_for_real(column_family, "", [options],
|
200
|
+
READ_DEFAULTS.merge(:start_key => nil,
|
201
|
+
:finish_key => nil,
|
202
|
+
:key_count => 100,
|
203
|
+
:columns => nil,
|
204
|
+
:reversed => false
|
205
|
+
)
|
206
|
+
)
|
207
|
+
res = _get_range(column_family,
|
208
|
+
options[:start_key],
|
209
|
+
options[:finish_key],
|
210
|
+
options[:key_count],
|
211
|
+
options[:columns],
|
212
|
+
options[:start],
|
213
|
+
options[:finish],
|
214
|
+
options[:count],
|
215
|
+
options[:consistency],
|
216
|
+
options[:reversed], &blk)
|
217
|
+
|
218
|
+
if blk.nil?
|
219
|
+
res
|
220
|
+
else
|
221
|
+
nil
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_range_keys(column_family, options = {})
|
226
|
+
get_range(column_family,options.merge!(:columns => [])).keys
|
187
227
|
end
|
188
228
|
|
189
|
-
def count_range(column_family, options={})
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
229
|
+
def count_range(column_family, options = {})
|
230
|
+
Hash[get_range(column_family, options).select{|k,v| v.length > 0}].keys.compact.length
|
231
|
+
end
|
232
|
+
|
233
|
+
def each_key(column_family, options = {})
|
234
|
+
each(column_family, options.merge!(:columns => [])) do |key, value|
|
235
|
+
yield key
|
196
236
|
end
|
197
|
-
count
|
198
237
|
end
|
199
238
|
|
200
|
-
def
|
201
|
-
|
202
|
-
|
239
|
+
def each(column_family, options = {})
|
240
|
+
batch_size = options.delete(:batch_size) || 100
|
241
|
+
count = options.delete(:key_count)
|
242
|
+
yielded_count = 0
|
243
|
+
|
244
|
+
options[:start_key] ||= ''
|
245
|
+
last_key = nil
|
246
|
+
|
247
|
+
while options[:start_key] != last_key && (count.nil? || count > yielded_count)
|
248
|
+
options[:start_key] = last_key
|
249
|
+
res = get_range(column_family, options.merge!(:start_key => last_key, :key_count => batch_size))
|
250
|
+
res.each do |key, columns|
|
251
|
+
next if options[:start_key] == key
|
252
|
+
next if yielded_count == count
|
253
|
+
yield key, columns
|
254
|
+
yielded_count += 1
|
255
|
+
last_key = key
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def create_index(ks_name, cf_name, c_name, v_class)
|
261
|
+
if @indexes[ks_name] &&
|
262
|
+
@indexes[ks_name][cf_name] &&
|
263
|
+
@indexes[ks_name][cf_name][c_name]
|
264
|
+
nil
|
265
|
+
|
203
266
|
else
|
204
|
-
@
|
267
|
+
@indexes[ks_name] ||= {}
|
268
|
+
@indexes[ks_name][cf_name] ||= {}
|
269
|
+
@indexes[ks_name][cf_name][c_name] = true
|
205
270
|
end
|
206
271
|
end
|
207
272
|
|
208
|
-
|
273
|
+
def drop_index(ks_name, cf_name, c_name)
|
274
|
+
if @indexes[ks_name] &&
|
275
|
+
@indexes[ks_name][cf_name] &&
|
276
|
+
@indexes[ks_name][cf_name][c_name]
|
209
277
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
finish = to_compare_with_type(finish, column_family)
|
214
|
-
cf(column_family).keys.sort.each do |key|
|
215
|
-
break if ret.keys.size >= count
|
216
|
-
if (start.nil? || key >= start) && (finish.nil? || key <= finish)
|
217
|
-
ret[key] = cf(column_family)[key]
|
218
|
-
end
|
278
|
+
@indexes[ks_name][cf_name].delete(c_name)
|
279
|
+
else
|
280
|
+
nil
|
219
281
|
end
|
220
|
-
ret
|
221
282
|
end
|
222
283
|
|
223
|
-
def
|
224
|
-
|
284
|
+
def create_index_expression(c_name, value, op)
|
285
|
+
{:column_name => c_name, :value => value, :comparison => op}
|
286
|
+
end
|
287
|
+
alias :create_idx_expr :create_index_expression
|
288
|
+
|
289
|
+
def create_index_clause(idx_expressions, start = "", count = 100)
|
290
|
+
{:start => start, :index_expressions => idx_expressions, :count => count, :type => :index_clause}
|
291
|
+
end
|
292
|
+
alias :create_idx_clause :create_index_clause
|
293
|
+
|
294
|
+
def get_indexed_slices(column_family, idx_clause, *columns_and_options)
|
295
|
+
column_family, columns, _, options =
|
296
|
+
extract_and_validate_params_for_real(column_family, [], columns_and_options, READ_DEFAULTS.merge(:key_count => 100, :key_start => ""))
|
297
|
+
|
298
|
+
unless [Hash, OrderedHash].include?(idx_clause.class) && idx_clause[:type] == :index_clause
|
299
|
+
idx_clause = create_index_clause(idx_clause, options[:key_start], options[:key_count])
|
300
|
+
end
|
301
|
+
|
225
302
|
ret = {}
|
226
|
-
|
227
|
-
|
228
|
-
if
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
else
|
237
|
-
ret[cf['Name']]['Type'] = 'Standard'
|
303
|
+
cf(column_family).each do |key, row|
|
304
|
+
next if idx_clause[:start] != '' && key < idx_clause[:start]
|
305
|
+
next if ret.length == idx_clause[:count]
|
306
|
+
|
307
|
+
matches = []
|
308
|
+
idx_clause[:index_expressions].each do |expr|
|
309
|
+
next if row[expr[:column_name]].nil?
|
310
|
+
next unless row[expr[:column_name]].send(expr[:comparison].to_sym, expr[:value])
|
311
|
+
|
312
|
+
matches << expr
|
238
313
|
end
|
314
|
+
|
315
|
+
ret[key] = row if matches.length == idx_clause[:index_expressions].length
|
239
316
|
end
|
317
|
+
|
240
318
|
ret
|
241
319
|
end
|
242
320
|
|
243
|
-
def
|
244
|
-
|
321
|
+
def add(column_family, key, value, *columns_and_options)
|
322
|
+
column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
|
323
|
+
|
324
|
+
if is_super(column_family)
|
325
|
+
cf(column_family)[key] ||= OrderedHash.new
|
326
|
+
cf(column_family)[key][column] ||= OrderedHash.new
|
327
|
+
cf(column_family)[key][column][sub_column] ||= 0
|
328
|
+
cf(column_family)[key][column][sub_column] += value
|
329
|
+
else
|
330
|
+
cf(column_family)[key] ||= OrderedHash.new
|
331
|
+
cf(column_family)[key][column] ||= 0
|
332
|
+
cf(column_family)[key][column] += value
|
333
|
+
end
|
334
|
+
|
335
|
+
nil
|
336
|
+
end
|
337
|
+
|
338
|
+
def column_families
|
339
|
+
cf_defs = {}
|
340
|
+
schema.each do |key, value|
|
341
|
+
cf_def = Cassandra::ColumnFamily.new
|
342
|
+
|
343
|
+
value.each do |property, property_value|
|
344
|
+
cf_def.send(:"#{property}=", property_value)
|
345
|
+
end
|
346
|
+
|
347
|
+
cf_defs[key] = cf_def
|
348
|
+
end
|
349
|
+
|
350
|
+
cf_defs
|
351
|
+
end
|
352
|
+
|
353
|
+
def schema(load=true)
|
354
|
+
@schema
|
355
|
+
end
|
356
|
+
|
357
|
+
def column_family_property(column_family, key)
|
358
|
+
schema[column_family.to_s][key]
|
359
|
+
end
|
360
|
+
|
361
|
+
def add_column_family(cf)
|
362
|
+
@schema[cf.name.to_s] ||= OrderedHash.new
|
363
|
+
|
364
|
+
cf.instance_variables.each do |var|
|
365
|
+
@schema[cf.name.to_s][var.slice(1..-1)] = cf.instance_variable_get(var)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def update_column_family(cf)
|
370
|
+
return false unless @schema.include?(cf.name.to_s)
|
371
|
+
|
372
|
+
cf.instance_variables.each do |var|
|
373
|
+
@schema[cf.name.to_s][var.slice(1..-1)] = cf.instance_variable_get(var)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def drop_column_family(column_family_name)
|
378
|
+
@schema.delete(column_family_name)
|
379
|
+
end
|
380
|
+
|
381
|
+
private
|
382
|
+
|
383
|
+
def schema_for_keyspace(keyspace)
|
384
|
+
@schema
|
385
|
+
end
|
386
|
+
|
387
|
+
def _get_range(column_family, start_key, finish_key, key_count, columns, start, finish, count, consistency, reversed, &blk)
|
388
|
+
ret = OrderedHash.new
|
389
|
+
start = to_compare_with_type(start, column_family)
|
390
|
+
finish = to_compare_with_type(finish, column_family)
|
391
|
+
cf(column_family).keys.sort.each do |key|
|
392
|
+
break if ret.keys.size >= key_count
|
393
|
+
if (start_key.nil? || key >= start_key) && (finish_key.nil? || key <= finish_key)
|
394
|
+
if columns
|
395
|
+
#ret[key] = columns.inject(OrderedHash.new){|hash, column_name| hash[column_name] = cf(column_family)[key][column_name]; hash;}
|
396
|
+
ret[key] = columns_to_hash(column_family, cf(column_family)[key].select{|k,v| columns.include?(k)})
|
397
|
+
ret[key] = apply_count(ret[key], count, reversed)
|
398
|
+
blk.call(key,ret[key]) unless blk.nil?
|
399
|
+
else
|
400
|
+
#ret[key] = apply_range(cf(column_family)[key], column_family, start, finish, !is_super(column_family))
|
401
|
+
start, finish = finish, start if reversed
|
402
|
+
ret[key] = apply_range(columns_to_hash(column_family, cf(column_family)[key]), column_family, start, finish)
|
403
|
+
ret[key] = apply_count(ret[key], count, reversed)
|
404
|
+
blk.call(key,ret[key]) unless blk.nil?
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
ret
|
245
409
|
end
|
246
410
|
|
247
411
|
def extract_and_validate_params_for_real(column_family, keys, args, options)
|
@@ -264,25 +428,12 @@ class Cassandra
|
|
264
428
|
def to_compare_with_type(column_name, column_family, standard=true)
|
265
429
|
return column_name if column_name.nil?
|
266
430
|
klass = if standard
|
267
|
-
|
431
|
+
column_name_class(column_family)
|
268
432
|
else
|
269
|
-
|
433
|
+
sub_column_name_class(column_family)
|
270
434
|
end
|
271
435
|
|
272
|
-
|
273
|
-
when "org.apache.cassandra.db.marshal.UTF8Type", "org.apache.cassandra.db.marshal.BytesType"
|
274
|
-
column_name
|
275
|
-
when "org.apache.cassandra.db.marshal.TimeUUIDType"
|
276
|
-
SimpleUUID::UUID.new(column_name)
|
277
|
-
when "org.apache.cassandra.db.marshal.LongType"
|
278
|
-
Long.new(column_name)
|
279
|
-
else
|
280
|
-
raise "Unknown column family type: #{klass.inspect}"
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
def column_family_type(column_family)
|
285
|
-
schema[column_family.to_s]['Type']
|
436
|
+
klass.new(column_name)
|
286
437
|
end
|
287
438
|
|
288
439
|
def cf(column_family)
|
@@ -293,9 +444,32 @@ class Cassandra
|
|
293
444
|
if new_stuff.is_a?(Array)
|
294
445
|
new_stuff = new_stuff.inject({}){|h,k| h[k] = nil; h }
|
295
446
|
end
|
447
|
+
|
448
|
+
new_stuff = new_stuff.to_a.inject({}){|h,k| h[k[0].to_s] = k[1]; h }
|
449
|
+
|
296
450
|
OrderedHash[old_stuff.merge(new_stuff).sort{|a,b| a[0] <=> b[0]}]
|
297
451
|
end
|
298
452
|
|
453
|
+
def columns_to_hash(column_family, columns)
|
454
|
+
column_class, sub_column_class = column_name_class(column_family), sub_column_name_class(column_family)
|
455
|
+
output = OrderedHash.new
|
456
|
+
|
457
|
+
columns.each do |column_name, value|
|
458
|
+
column = column_class.new(column_name)
|
459
|
+
|
460
|
+
if [Hash, OrderedHash].include?(value.class)
|
461
|
+
output[column] ||= OrderedHash.new
|
462
|
+
value.each do |sub_column, sub_column_value|
|
463
|
+
output[column][sub_column_class.new(sub_column)] = sub_column_value
|
464
|
+
end
|
465
|
+
else
|
466
|
+
output[column_class.new(column_name)] = value
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
output
|
471
|
+
end
|
472
|
+
|
299
473
|
def apply_count(row, count, reversed=false)
|
300
474
|
if count
|
301
475
|
keys = row.keys.sort
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# OrderedHash is namespaced to prevent conflicts with other implementations
|
2
2
|
class Cassandra
|
3
|
-
# Hash is ordered in Ruby 1.9!
|
4
|
-
if RUBY_VERSION >= '1.9'
|
5
|
-
OrderedHashInt = ::Hash
|
6
|
-
else
|
7
3
|
class OrderedHashInt < Hash #:nodoc:
|
8
4
|
def initialize(*args, &block)
|
9
5
|
super
|
@@ -126,6 +122,10 @@ class Cassandra
|
|
126
122
|
@keys = other.keys
|
127
123
|
self
|
128
124
|
end
|
125
|
+
|
126
|
+
def reverse
|
127
|
+
OrderedHashInt[self.to_a.reverse]
|
128
|
+
end
|
129
129
|
|
130
130
|
private
|
131
131
|
|
@@ -133,11 +133,10 @@ class Cassandra
|
|
133
133
|
@keys.delete_if {|k| !has_key?(k)}
|
134
134
|
end
|
135
135
|
end
|
136
|
-
end
|
137
136
|
|
138
137
|
class OrderedHash < OrderedHashInt #:nodoc:
|
139
138
|
def initialize(*args, &block)
|
140
|
-
@timestamps =
|
139
|
+
@timestamps = OrderedHashInt.new
|
141
140
|
super
|
142
141
|
end
|
143
142
|
|
@@ -156,13 +155,13 @@ class Cassandra
|
|
156
155
|
super
|
157
156
|
end
|
158
157
|
|
159
|
-
def delete_if
|
160
|
-
@timestamps.delete_if
|
158
|
+
def delete_if(&block)
|
159
|
+
@timestamps.delete_if(&block)
|
161
160
|
super
|
162
161
|
end
|
163
162
|
|
164
|
-
def reject!
|
165
|
-
@timestamps.reject!
|
163
|
+
def reject!(&block)
|
164
|
+
@timestamps.reject!(&block)
|
166
165
|
super
|
167
166
|
end
|
168
167
|
|
@@ -189,12 +188,5 @@ class Cassandra
|
|
189
188
|
def inspect
|
190
189
|
"#<OrderedHash #{super}--TimeStamps: #{@timestamps.inspect}>"
|
191
190
|
end
|
192
|
-
|
193
|
-
private
|
194
|
-
|
195
|
-
def sync_keys!
|
196
|
-
@timestamps.delete_if {|k,v| !has_key?(k)}
|
197
|
-
super
|
198
|
-
end
|
199
191
|
end
|
200
|
-
end
|
192
|
+
end
|