hbase-jruby 0.3.5-java → 0.4.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +13 -0
- data/README.md +135 -30
- data/lib/hbase-jruby/batch_exception.rb +12 -0
- data/lib/hbase-jruby/byte_array.rb +6 -0
- data/lib/hbase-jruby/dependency.rb +6 -4
- data/lib/hbase-jruby/row.rb +8 -2
- data/lib/hbase-jruby/schema.rb +2 -1
- data/lib/hbase-jruby/scoped.rb +7 -4
- data/lib/hbase-jruby/table/batch_action.rb +69 -0
- data/lib/hbase-jruby/table/checked_operation.rb +11 -8
- data/lib/hbase-jruby/table/mutation.rb +130 -0
- data/lib/hbase-jruby/table.rb +130 -82
- data/lib/hbase-jruby/version.rb +1 -1
- data/lib/hbase-jruby.rb +3 -0
- data/test/helper.rb +8 -1
- data/test/test_byte_array.rb +4 -0
- data/test/test_schema.rb +123 -67
- data/test/test_table.rb +266 -120
- metadata +5 -2
data/lib/hbase-jruby/table.rb
CHANGED
@@ -43,7 +43,7 @@ class Table
|
|
43
43
|
|
44
44
|
[:get, :count, :aggregate,
|
45
45
|
:range, :project, :filter, :while,
|
46
|
-
:limit, :versions, :caching, :batch,
|
46
|
+
:limit, :versions, :caching, # :batch,
|
47
47
|
:time_range, :at
|
48
48
|
].each do |method|
|
49
49
|
define_method(method) do |*args|
|
@@ -72,11 +72,11 @@ class Table
|
|
72
72
|
def put *args
|
73
73
|
case args.length
|
74
74
|
when 1
|
75
|
-
puts = args.first.map { |rowkey, props|
|
75
|
+
puts = args.first.map { |rowkey, props| @mutation.put rowkey, props }
|
76
76
|
htable.put puts
|
77
77
|
puts.length
|
78
78
|
when 2
|
79
|
-
htable.put
|
79
|
+
htable.put @mutation.put(*args)
|
80
80
|
1
|
81
81
|
else
|
82
82
|
raise ArgumentError, 'invalid number of arguments'
|
@@ -125,14 +125,24 @@ class Table
|
|
125
125
|
def delete *args
|
126
126
|
specs = args.first.is_a?(Array) ? args : [args]
|
127
127
|
|
128
|
-
|
128
|
+
list = specs.map { |spec| spec.empty? ? nil : @mutation.delete(*spec) }.compact
|
129
|
+
if list.length == 1
|
130
|
+
htable.delete list.first
|
131
|
+
else
|
132
|
+
htable.delete list
|
133
|
+
end
|
129
134
|
end
|
130
135
|
|
131
136
|
# Delete rows.
|
132
137
|
# @param [*Object] rowkeys List of rowkeys of rows to delete
|
133
138
|
# @return [nil]
|
134
139
|
def delete_row *rowkeys
|
135
|
-
|
140
|
+
list = rowkeys.map { |rk| Delete.new(Util.to_bytes rk) }
|
141
|
+
if list.length == 1
|
142
|
+
htable.delete list.first
|
143
|
+
else
|
144
|
+
htable.delete list
|
145
|
+
end
|
136
146
|
end
|
137
147
|
|
138
148
|
# Atomically increase numeric values
|
@@ -141,41 +151,69 @@ class Table
|
|
141
151
|
# @param [Object] rowkey Rowkey
|
142
152
|
# @param [String, Array] column Column expression in String "FAMILY:QUALIFIER", or in Array [FAMILY, QUALIFIER]
|
143
153
|
# @param [Fixnum] by Increment amount
|
144
|
-
# @return [
|
154
|
+
# @return [Hash]
|
145
155
|
# @example
|
146
156
|
# table.increment('a000', 'cf1:col1', 1)
|
147
157
|
# @overload increment(rowkey, column_by_hash)
|
148
158
|
# Atomically increase values of multiple columns
|
149
159
|
# @param [Object] rowkey Rowkey
|
150
160
|
# @param [Hash] column_by_hash Column expression to increment amount pairs
|
161
|
+
# @return [Hash]
|
151
162
|
# @example
|
152
163
|
# table.increment('a000', 'cf1:col1' => 1, 'cf1:col2' => 2)
|
153
164
|
# @overload increment(inc_spec)
|
154
165
|
# Increase values of multiple columns from multiple rows.
|
155
166
|
# @param [Hash] inc_spec { rowkey => { col => by } }
|
167
|
+
# @return [Hash]
|
156
168
|
# @example
|
157
169
|
# table.increment 'a000' => { 'cf1:col1' => 1, 'cf1:col2' => 2 },
|
158
170
|
# 'a001' => { 'cf1:col1' => 3, 'cf1:col2' => 4 }
|
159
171
|
def increment rowkey, *args
|
160
172
|
if args.empty? && rowkey.is_a?(Hash)
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
elsif args.first.is_a?(Hash)
|
165
|
-
cols = args.first
|
166
|
-
htable.increment Increment.new(Util.to_bytes rowkey).tap { |inc|
|
167
|
-
cols.each do |col, by|
|
168
|
-
cf, cq, _ = lookup_and_parse col
|
169
|
-
inc.addColumn cf, cq, by
|
173
|
+
INSENSITIVE_ROW_HASH.clone.tap { |result|
|
174
|
+
rowkey.each do |key, spec|
|
175
|
+
result[Util.java_bytes?(key) ? ByteArray[key] : key] = increment(key, spec)
|
170
176
|
end
|
171
177
|
}
|
172
178
|
else
|
173
|
-
|
174
|
-
|
175
|
-
|
179
|
+
incr = @mutation.increment(rowkey, *args)
|
180
|
+
Row.send(:new, self, htable.increment(incr)).to_h.tap { |h|
|
181
|
+
h.each do |k, v|
|
182
|
+
h[k] = Util.from_bytes :fixnum, v unless v.is_a?(Fixnum)
|
183
|
+
end
|
184
|
+
}
|
176
185
|
end
|
177
186
|
end
|
178
187
|
|
188
|
+
# Appends values to one or more columns within a single row.
|
189
|
+
# @param [Object] rowkey Rowkey
|
190
|
+
# @param [Hash] spec Hash (column to value)
|
191
|
+
# @return [Hash] Updated values
|
192
|
+
# @example
|
193
|
+
# table.put :rowkey, col1: 'hello', col2: 'foo'
|
194
|
+
# table.append :rowkey, col1: ' world', col2: 'bar'
|
195
|
+
# # { col1: 'hello world', col2: 'foobar' }
|
196
|
+
def append rowkey, spec
|
197
|
+
result = htable.append @mutation.append(rowkey, spec)
|
198
|
+
Row.send(:new, self, result).to_h if result # (maybe null)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Performs multiple mutations atomically on a single row.
|
202
|
+
# Currently Put and Delete are supported.
|
203
|
+
# The mutations are performed in the order in which they were specified.
|
204
|
+
# @param [Object] rowkey Rowkey
|
205
|
+
# @yield [HBase::Table::Mutation::Mutator]
|
206
|
+
# @return [nil]
|
207
|
+
# @example
|
208
|
+
# table.mutate do |m|
|
209
|
+
# m.put a: 100, b: 'hello'
|
210
|
+
# m.delete :c, :d
|
211
|
+
# m.put e: 3.14
|
212
|
+
# end
|
213
|
+
def mutate(rowkey, &block)
|
214
|
+
htable.mutateRow @mutation.mutate(rowkey, &block)
|
215
|
+
end
|
216
|
+
|
179
217
|
# Scan through the table
|
180
218
|
# @yield [row] Yields each row in the scope
|
181
219
|
# @yieldparam [HBase::Row] row
|
@@ -187,7 +225,7 @@ class Table
|
|
187
225
|
# Returns HBase::Scoped object for this table
|
188
226
|
# @return [HBase::Scoped]
|
189
227
|
def scoped
|
190
|
-
Scoped.send(:new, self)
|
228
|
+
Scoped.send(:new, self, @hbase.config.get('hbase.client.scanner.caching').to_i)
|
191
229
|
end
|
192
230
|
|
193
231
|
# Returns CheckedOperation instance for check-and-put and check-and-delete
|
@@ -198,22 +236,82 @@ class Table
|
|
198
236
|
raise ArgumentError, 'invalid check condition' unless cond.length == 1
|
199
237
|
col, val = cond.first
|
200
238
|
|
201
|
-
cf, cq, type = lookup_and_parse(col)
|
239
|
+
cf, cq, type = lookup_and_parse(col, true)
|
202
240
|
|
203
241
|
# If the passed value is null, the check is for the lack of column
|
204
|
-
CheckedOperation.new self, Util.to_bytes(rowkey),
|
242
|
+
CheckedOperation.new self, @mutation, Util.to_bytes(rowkey),
|
205
243
|
cf, cq,
|
206
244
|
(val.nil? ? nil : Util.to_typed_bytes(type, val))
|
207
245
|
end
|
208
246
|
|
247
|
+
# Method that does a batch call on Deletes, Gets, Puts, Increments, Appends
|
248
|
+
# and RowMutations. The ordering of execution of the actions is not defined.
|
249
|
+
# An Array of Hashes are returned as the results of each operation. For
|
250
|
+
# Delete, Put, and RowMutation, :result entry of the returned Hash is
|
251
|
+
# Boolean. For Increment and Append, it will be plain Hashes, and for Get,
|
252
|
+
# HBase::Rows will be returned.
|
253
|
+
# When an error has occurred, you can still access the partial results using
|
254
|
+
# `results` method of the thrown BatchException instance.
|
255
|
+
# @yield [HBase::Table::BatchAction]
|
256
|
+
# @return [Array<Hash>]
|
257
|
+
# @raise [HBase::BatchException]
|
258
|
+
def batch arg = nil
|
259
|
+
if arg
|
260
|
+
# Backward compatibility
|
261
|
+
return scoped.batch(arg)
|
262
|
+
else
|
263
|
+
raise ArgumentError, "Block not given" unless block_given?
|
264
|
+
end
|
265
|
+
b = BatchAction.send(:new, self, @mutation)
|
266
|
+
yield b
|
267
|
+
results = Array.new(b.actions.length).to_java
|
268
|
+
process = lambda do
|
269
|
+
results.each_with_index do |r, idx|
|
270
|
+
action = b.actions[idx]
|
271
|
+
type = action[:type]
|
272
|
+
case type
|
273
|
+
when :get
|
274
|
+
action[:result] = (r.nil? || r.empty?) ? nil : Row.send(:new, self, r)
|
275
|
+
when :append
|
276
|
+
action[:result] = r && Row.send(:new, self, r).to_h
|
277
|
+
when :increment
|
278
|
+
action[:result] = r &&
|
279
|
+
Row.send(:new, self, r).to_h.tap { |h|
|
280
|
+
h.each do |k, v|
|
281
|
+
h[k] = Util.from_bytes :fixnum, v unless v.is_a?(Fixnum)
|
282
|
+
end
|
283
|
+
}
|
284
|
+
else
|
285
|
+
case r
|
286
|
+
when java.lang.Exception
|
287
|
+
action[:result] = false
|
288
|
+
action[:exception] = r
|
289
|
+
when nil
|
290
|
+
action[:result] = false
|
291
|
+
else
|
292
|
+
action[:result] = true
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
b.actions
|
297
|
+
end
|
298
|
+
|
299
|
+
begin
|
300
|
+
htable.batch b.actions.map { |a| a[:action] }, results
|
301
|
+
process.call
|
302
|
+
rescue Exception => e
|
303
|
+
raise HBase::BatchException.new(e, process.call)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
209
307
|
# @private
|
210
308
|
def lookup_schema col
|
211
309
|
@hbase.schema.lookup @name_sym, col
|
212
310
|
end
|
213
311
|
|
214
312
|
# @private
|
215
|
-
def lookup_and_parse col
|
216
|
-
@hbase.schema.lookup_and_parse @name_sym, col
|
313
|
+
def lookup_and_parse col, expect_cq
|
314
|
+
@hbase.schema.lookup_and_parse @name_sym, col, expect_cq
|
217
315
|
end
|
218
316
|
|
219
317
|
private
|
@@ -222,73 +320,23 @@ private
|
|
222
320
|
@config = config
|
223
321
|
@name = name.to_s
|
224
322
|
@name_sym = name.to_sym
|
323
|
+
@mutation = Mutation.new(self)
|
225
324
|
end
|
226
325
|
|
227
326
|
def check_closed
|
228
327
|
raise RuntimeError, "HBase connection is already closed" if @hbase.closed?
|
229
328
|
end
|
230
329
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
cf, cq, type = lookup_and_parse col
|
237
|
-
|
238
|
-
case val
|
239
|
-
when Hash
|
240
|
-
val.each do |t, v|
|
241
|
-
case t
|
242
|
-
# Timestamp / Ruby Time
|
243
|
-
when Time, Fixnum
|
244
|
-
put.add cf, cq, time_to_long(t), Util.to_typed_bytes(type, v)
|
245
|
-
# Types: :byte, :short, :int, ...
|
246
|
-
else
|
247
|
-
put.add cf, cq, Util.to_typed_bytes(t, v)
|
248
|
-
end unless v.nil?
|
249
|
-
end
|
250
|
-
else
|
251
|
-
put.add cf, cq, Util.to_typed_bytes(type, val)
|
330
|
+
INSENSITIVE_ROW_HASH = {}.tap { |h|
|
331
|
+
h.instance_eval do
|
332
|
+
def [] key
|
333
|
+
if Util.java_bytes?(key)
|
334
|
+
key = ByteArray[key]
|
252
335
|
end
|
336
|
+
super key
|
253
337
|
end
|
254
|
-
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
|
-
def make_delete rowkey, *extra
|
259
|
-
Delete.new(Util.to_bytes rowkey).tap { |del|
|
260
|
-
cf = cq = nil
|
261
|
-
prcd = false
|
262
|
-
|
263
|
-
prc = lambda do
|
264
|
-
unless prcd
|
265
|
-
if cq
|
266
|
-
# Delete all versions
|
267
|
-
del.deleteColumns cf, cq
|
268
|
-
elsif cf
|
269
|
-
del.deleteFamily cf
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
extra.each do |x|
|
275
|
-
case x
|
276
|
-
when Fixnum, Time
|
277
|
-
if cq
|
278
|
-
del.deleteColumn cf, cq, time_to_long(x)
|
279
|
-
prcd = true
|
280
|
-
else
|
281
|
-
raise ArgumentError, 'qualifier not given'
|
282
|
-
end
|
283
|
-
else
|
284
|
-
prc.call
|
285
|
-
cf, cq, _ = lookup_and_parse x
|
286
|
-
prcd = false
|
287
|
-
end
|
288
|
-
end
|
289
|
-
prc.call
|
290
|
-
}
|
291
|
-
end
|
338
|
+
end
|
339
|
+
}
|
292
340
|
end#Table
|
293
341
|
end#HBase
|
294
342
|
|
data/lib/hbase-jruby/version.rb
CHANGED
data/lib/hbase-jruby.rb
CHANGED
@@ -11,7 +11,10 @@ require 'hbase-jruby/admin'
|
|
11
11
|
require 'hbase-jruby/scoped/aggregation'
|
12
12
|
require 'hbase-jruby/scoped'
|
13
13
|
require 'hbase-jruby/schema'
|
14
|
+
require 'hbase-jruby/batch_exception'
|
14
15
|
require 'hbase-jruby/table'
|
16
|
+
require 'hbase-jruby/table/mutation'
|
17
|
+
require 'hbase-jruby/table/batch_action'
|
15
18
|
require 'hbase-jruby/table/admin'
|
16
19
|
require 'hbase-jruby/table/inspection'
|
17
20
|
require 'hbase-jruby/table/checked_operation'
|
data/test/helper.rb
CHANGED
@@ -12,6 +12,7 @@ unless defined? Enumerator
|
|
12
12
|
end
|
13
13
|
|
14
14
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
15
|
+
$rowkey = Time.now.to_i
|
15
16
|
|
16
17
|
require "hbase-jruby"
|
17
18
|
if dist = ENV['HBASE_JRUBY_TEST_DIST']
|
@@ -31,7 +32,9 @@ class TestHBaseJRubyBase < Test::Unit::TestCase
|
|
31
32
|
hbase.close
|
32
33
|
|
33
34
|
def connect
|
34
|
-
HBase.new
|
35
|
+
HBase.new('hbase.zookeeper.quorum' => ZK,
|
36
|
+
'hbase.client.retries.number' => 10,
|
37
|
+
'hbase.client.scanner.caching' => 100)
|
35
38
|
end
|
36
39
|
|
37
40
|
def setup
|
@@ -53,6 +56,10 @@ class TestHBaseJRubyBase < Test::Unit::TestCase
|
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
59
|
+
def next_rowkey
|
60
|
+
$rowkey += 1
|
61
|
+
end
|
62
|
+
|
56
63
|
def teardown
|
57
64
|
if RECREATE
|
58
65
|
@table.drop! if @table && @table.exists?
|
data/test/test_byte_array.rb
CHANGED
data/test/test_schema.rb
CHANGED
@@ -52,17 +52,19 @@ class TestSchema < TestHBaseJRubyBase
|
|
52
52
|
}
|
53
53
|
|
54
54
|
# PUT
|
55
|
-
|
55
|
+
rk1 = next_rowkey
|
56
|
+
rk2 = next_rowkey
|
57
|
+
@table.put rk1, 'cf1:a' => data[:a], 'cf1:b' => data[:b], 'cf1:c' => data[:c],
|
56
58
|
'cf1:d' => data[:d], 'cf1:d2' => data[:d2], 'cf2:e' => data[:e],
|
57
59
|
'cf3:f' => data[:f], 'cf1:x' => data[[:cf1, HBase::ByteArray['x']]]
|
58
|
-
@table.put
|
60
|
+
@table.put rk2, data
|
59
61
|
|
60
62
|
# GET
|
61
|
-
row = @table.get(
|
62
|
-
assert_equal Set[ *@table.get(
|
63
|
-
Set[ *
|
64
|
-
assert_equal Set[ *@table.get(
|
65
|
-
assert_equal Set[ *data.keys ],
|
63
|
+
row = @table.get(rk2)
|
64
|
+
assert_equal Set[ *@table.get(rk1).to_h.values.map { |b| HBase::ByteArray.new b }],
|
65
|
+
Set[ * row.to_h.values.map { |b| HBase::ByteArray.new b }]
|
66
|
+
assert_equal Set[ *@table.get(rk1).to_h.keys ], Set[ *row.to_h.keys ]
|
67
|
+
assert_equal Set[ *data.keys ], Set[ *row.to_h.keys ]
|
66
68
|
|
67
69
|
assert_equal data[:a], row[:a]
|
68
70
|
assert_equal data[:a], row['a']
|
@@ -84,17 +86,20 @@ class TestSchema < TestHBaseJRubyBase
|
|
84
86
|
|
85
87
|
assert_equal data[[:cf1, HBase::ByteArray['x']]], HBase::Util.from_bytes(:long, row['cf1:x'])
|
86
88
|
|
87
|
-
data1 = @table.get(
|
89
|
+
data1 = @table.get(rk1).to_h
|
88
90
|
data1[:a] *= 2
|
89
91
|
data1[:b] = :new_symbol
|
90
|
-
|
91
|
-
|
92
|
+
|
93
|
+
rk3 = next_rowkey
|
94
|
+
@table.put rk3, data1
|
95
|
+
ret = @table.increment rk3, :a => 5
|
92
96
|
|
93
97
|
# PUT again
|
94
|
-
assert_equal data[:a] * 2 + 5,
|
95
|
-
assert_equal :
|
96
|
-
assert_equal :new_symbol, @table.get(
|
97
|
-
assert_equal :new_symbol, @table.get(
|
98
|
+
assert_equal data[:a] * 2 + 5, ret[:a]
|
99
|
+
assert_equal data[:a] * 2 + 5, @table.get(rk3)[:a]
|
100
|
+
assert_equal :new_symbol, @table.get(rk3)[:b]
|
101
|
+
assert_equal :new_symbol, @table.get(rk3)['b']
|
102
|
+
assert_equal :new_symbol, @table.get(rk3)['cf1:b']
|
98
103
|
|
99
104
|
# PROJECT
|
100
105
|
assert_equal [:a, :c, :e, :f],
|
@@ -110,17 +115,18 @@ class TestSchema < TestHBaseJRubyBase
|
|
110
115
|
assert_equal 1, @table.filter(:a => { :gt => 150 }).count
|
111
116
|
|
112
117
|
# cf:g (automatic type conversion)
|
113
|
-
@table.put
|
114
|
-
assert_equal 3.14, @table.get(
|
115
|
-
@table.put
|
116
|
-
assert_equal 314, @table.get(
|
118
|
+
@table.put rk3, :g => 3.14
|
119
|
+
assert_equal 3.14, @table.get(rk3)[:g]
|
120
|
+
@table.put rk3, :g => 314
|
121
|
+
assert_equal 314, @table.get(rk3)[:g]
|
117
122
|
|
118
123
|
# cf3:g vs. cf2:g
|
119
|
-
|
120
|
-
|
121
|
-
assert_equal
|
122
|
-
assert_equal
|
123
|
-
assert_equal
|
124
|
+
rk4 = next_rowkey
|
125
|
+
@table.put rk4, :g => 3.14, 'cf2:g' => 'String'
|
126
|
+
assert_equal 3.14, @table.get(rk4)[:g]
|
127
|
+
assert_equal 'String', @table.get(rk4)['cf2:g'].to_s
|
128
|
+
assert_equal 3.14, @table.get(rk4).to_h[:g]
|
129
|
+
assert_equal 'String', @table.get(rk4).to_h['cf2:g'].to_s
|
124
130
|
end
|
125
131
|
|
126
132
|
def test_schema_readme
|
@@ -152,9 +158,10 @@ class TestSchema < TestHBaseJRubyBase
|
|
152
158
|
:alive => true
|
153
159
|
}
|
154
160
|
|
155
|
-
|
161
|
+
rk = next_rowkey
|
162
|
+
@table.put(rk => data)
|
156
163
|
|
157
|
-
john = @table.get(
|
164
|
+
john = @table.get(rk)
|
158
165
|
|
159
166
|
data.each do |k, v|
|
160
167
|
assert_equal v, john[k]
|
@@ -170,6 +177,7 @@ class TestSchema < TestHBaseJRubyBase
|
|
170
177
|
|
171
178
|
def test_schema_book
|
172
179
|
table = @table
|
180
|
+
rk = next_rowkey
|
173
181
|
|
174
182
|
@hbase.schema[table.name] = {
|
175
183
|
# Columns in cf1 family
|
@@ -210,12 +218,12 @@ class TestSchema < TestHBaseJRubyBase
|
|
210
218
|
:comment1 => 'A must-have',
|
211
219
|
:comment2 => 'Rewarding purchase'
|
212
220
|
}
|
213
|
-
table.put
|
221
|
+
table.put rk, data
|
214
222
|
# Since we can't directly compare java byte arrays
|
215
223
|
data[:image] = HBase::ByteArray[ data[:image] ]
|
216
224
|
|
217
225
|
# Get data (rowkey: 1)
|
218
|
-
book = table.get
|
226
|
+
book = table.get rk
|
219
227
|
|
220
228
|
assert_equal data, book.to_h.tap { |h| h[:image] = HBase::ByteArray[ h[:image] ] }
|
221
229
|
assert_equal data[:title], book['title']
|
@@ -229,13 +237,15 @@ class TestSchema < TestHBaseJRubyBase
|
|
229
237
|
assert_equal true, book.to_H.values.map(&:keys).flatten.all? { |e| e.is_a? Fixnum }
|
230
238
|
|
231
239
|
# Scan table
|
232
|
-
|
233
|
-
assert_equal
|
234
|
-
assert_equal
|
235
|
-
assert_equal 1, table.range(
|
236
|
-
assert_equal 1, table.range(
|
240
|
+
range = (rk - 1)..(rk + 1)
|
241
|
+
assert_equal 1890, table.range(range).first[:year]
|
242
|
+
assert_equal 2, table.range(range).first.raw(:year).length
|
243
|
+
assert_equal 1, table.range(range).filter(:year => 1890).to_a.length
|
244
|
+
assert_equal 1, table.range(range).filter(:year => 1890).count
|
245
|
+
assert_equal 1, table.range(range).filter(:year => 1880...1900).count
|
237
246
|
cnt = 0
|
238
|
-
|
247
|
+
inc1 = inc2 = nil
|
248
|
+
table.range(range).
|
239
249
|
filter(:year => 1880...1900,
|
240
250
|
:in_print => true,
|
241
251
|
:category => ['Comics', 'Fiction', /cult/i],
|
@@ -253,27 +263,33 @@ class TestSchema < TestHBaseJRubyBase
|
|
253
263
|
table.put book.rowkey => { :price => book[:price] + BigDecimal('1') }
|
254
264
|
|
255
265
|
# Atomic increment
|
256
|
-
table.increment book.rowkey
|
266
|
+
inc1 = table.increment book.rowkey => { :reviews => 1, :stars => 2 }
|
267
|
+
inc2 = table.increment book.rowkey, :stars => 3
|
257
268
|
cnt += 1
|
258
269
|
end
|
259
270
|
assert_equal 1, cnt
|
260
271
|
|
261
|
-
assert_equal data[:price] + 1.0, table.get(
|
262
|
-
assert_equal data[:reviews] + 1, table.get(
|
263
|
-
assert_equal data[:stars] + 5, table.get(
|
272
|
+
assert_equal data[:price] + 1.0, table.get(rk)[:price]
|
273
|
+
assert_equal data[:reviews] + 1, table.get(rk)[:reviews]
|
274
|
+
assert_equal data[:stars] + 5, table.get(rk)[:stars]
|
275
|
+
|
276
|
+
assert_equal data[:reviews] + 1, inc1[book.rowkey][:reviews]
|
277
|
+
assert_equal data[:stars] + 2, inc1[book.rowkey][:stars]
|
278
|
+
assert_equal nil, inc2[:reviews]
|
279
|
+
assert_equal data[:stars] + 5, inc2[:stars]
|
264
280
|
|
265
281
|
# Coprocessor
|
266
282
|
table.enable_aggregation!
|
267
|
-
table.put
|
283
|
+
table.put next_rowkey, :reviews => 100, :stars => 500
|
268
284
|
assert_equal data[:reviews] + 1 + data[:stars] + 5 + 100 + 500,
|
269
285
|
table.project(:reviews, :stars).aggregate(:sum)
|
270
286
|
#table.disable_aggregation!
|
271
287
|
|
272
288
|
# Undefined columns
|
273
|
-
table.put
|
274
|
-
table.put
|
275
|
-
table.put
|
276
|
-
assert_equal 1000, table.get(
|
289
|
+
table.put rk, 'cf1:x' => 1000
|
290
|
+
table.put rk, [:cf1, :y] => 2000
|
291
|
+
table.put rk, [:cf1, 2013] => 3000
|
292
|
+
assert_equal 1000, table.get(rk).fixnum('cf1:x')
|
277
293
|
|
278
294
|
[
|
279
295
|
[:cf1, HBase::ByteArray['x']],
|
@@ -284,30 +300,68 @@ class TestSchema < TestHBaseJRubyBase
|
|
284
300
|
%w[cf1 x],
|
285
301
|
'cf1:x'
|
286
302
|
].each do |param|
|
287
|
-
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(
|
288
|
-
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(
|
289
|
-
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(
|
303
|
+
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(rk)[param])
|
304
|
+
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(rk)[*param])
|
305
|
+
assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(rk).to_h[param])
|
290
306
|
end
|
291
307
|
|
292
|
-
assert_equal 2000, HBase::Util.from_bytes(:fixnum, table.get(
|
293
|
-
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(
|
294
|
-
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(
|
295
|
-
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(
|
296
|
-
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(
|
308
|
+
assert_equal 2000, HBase::Util.from_bytes(:fixnum, table.get(rk)[:cf1, :y])
|
309
|
+
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(rk)[:cf1, 2013])
|
310
|
+
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(rk)[[:cf1, 2013]])
|
311
|
+
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(rk).to_h[[:cf1, HBase::ByteArray[2013]]])
|
312
|
+
assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(rk).to_h[[:cf1, 2013]])
|
313
|
+
|
314
|
+
# Append string to title column
|
315
|
+
ret = table.append rk, :title => '!!!'
|
316
|
+
assert_equal data[:title] + '!!!', ret[:title]
|
317
|
+
assert_equal data[:title] + '!!!', table.get(rk)[:title]
|
318
|
+
|
319
|
+
# Mutation
|
320
|
+
table.mutate(rk) do |m|
|
321
|
+
m.delete :comment1, :comment2
|
322
|
+
m.put :comment3 => 'nice', :comment4 => 'great'
|
323
|
+
assert_raise(ArgumentError) {
|
324
|
+
m.put :some_unknown_column => 'perfect'
|
325
|
+
}
|
326
|
+
end
|
327
|
+
assert_equal nil, table.get(rk)[:comment1]
|
328
|
+
assert_equal nil, table.get(rk)[:comment2]
|
329
|
+
assert_equal 'nice', table.get(rk)[:comment3]
|
330
|
+
assert_equal 'great', table.get(rk)[:comment4]
|
331
|
+
|
332
|
+
# Batch
|
333
|
+
ret = table.batch do |b|
|
334
|
+
b.put rk, :comment5 => 'gnarly'
|
335
|
+
b.delete rk, :comment4
|
336
|
+
b.increment rk, :stars => 100, :reviews => 200
|
337
|
+
b.mutate(rk) do |m|
|
338
|
+
m.put :comment6 => 'rad'
|
339
|
+
m.delete :image
|
340
|
+
end
|
341
|
+
b.append rk, :category => '/Etc'
|
342
|
+
b.get rk
|
343
|
+
end
|
344
|
+
assert_equal 6, ret.length
|
345
|
+
assert_equal [true] * 3, ret.values_at(0, 1, 3).map { |r| r[:result] }
|
346
|
+
assert_equal data[:stars] + 5 + 100, ret[2][:result][:stars]
|
347
|
+
assert_equal data[:reviews] + 1 + 200, ret[2][:result][:reviews]
|
348
|
+
assert_equal data[:category] + '/Etc', ret[4][:result][:category]
|
349
|
+
assert_instance_of HBase::Row, ret[5][:result]
|
350
|
+
assert_equal 1890, ret[5][:result][:year]
|
297
351
|
|
298
352
|
# Delete :title column of book 1
|
299
|
-
table.delete
|
300
|
-
assert_equal nil, table.get(
|
301
|
-
assert_equal data[:author], table.get(
|
353
|
+
table.delete rk, :title
|
354
|
+
assert_equal nil, table.get(rk)[:title]
|
355
|
+
assert_equal data[:author], table.get(rk)[:author]
|
302
356
|
|
303
357
|
# Delete column family
|
304
|
-
table.delete
|
305
|
-
assert_equal nil, table.get(
|
306
|
-
assert_equal data[:summary], table.get(
|
358
|
+
table.delete rk, :cf1
|
359
|
+
assert_equal nil, table.get(rk)[:author]
|
360
|
+
assert_equal data[:summary], table.get(rk)[:summary]
|
307
361
|
|
308
362
|
# Delete book 1
|
309
|
-
table.delete
|
310
|
-
assert_equal nil, table.get(
|
363
|
+
table.delete rk
|
364
|
+
assert_equal nil, table.get(rk)
|
311
365
|
|
312
366
|
# Drop table for subsequent tests
|
313
367
|
table.drop!
|
@@ -323,11 +377,12 @@ class TestSchema < TestHBaseJRubyBase
|
|
323
377
|
}
|
324
378
|
}
|
325
379
|
|
380
|
+
rk = next_rowkey
|
326
381
|
assert_raise(ArgumentError) {
|
327
|
-
@table.put
|
382
|
+
@table.put rk, :a => nil, :b => nil, :c => nil, 'cf1:z' => nil
|
328
383
|
}
|
329
|
-
@table.put
|
330
|
-
h = @table.get(
|
384
|
+
@table.put rk, :a => nil, :b => nil, :c => nil, :d => 'yo', 'cf1:z' => 1000
|
385
|
+
h = @table.get(rk).to_h
|
331
386
|
assert !h.has_key?(:a)
|
332
387
|
assert !h.has_key?(:b)
|
333
388
|
assert !h.has_key?(:c)
|
@@ -345,14 +400,15 @@ class TestSchema < TestHBaseJRubyBase
|
|
345
400
|
:cf1 => { :a => :fixnum }
|
346
401
|
}
|
347
402
|
|
348
|
-
|
349
|
-
|
350
|
-
assert_equal 100, @table.get(
|
403
|
+
rk = next_rowkey
|
404
|
+
@table.put rk, :a => 100
|
405
|
+
assert_equal 100, @table.get(rk)[:a]
|
406
|
+
assert_equal 100, @table.get(rk)['cf1:a']
|
351
407
|
|
352
408
|
@hbase.schema.delete @table.name
|
353
|
-
|
354
|
-
assert_equal true, HBase::Util.java_bytes?(@table.get(
|
355
|
-
assert_equal 100, HBase::Util.from_bytes(:fixnum, @table.get(
|
409
|
+
assert_raise(ArgumentError) { @table.get(rk)[:a] }
|
410
|
+
assert_equal true, HBase::Util.java_bytes?(@table.get(rk)['cf1:a'])
|
411
|
+
assert_equal 100, HBase::Util.from_bytes(:fixnum, @table.get(rk)['cf1:a'])
|
356
412
|
end
|
357
413
|
end
|
358
414
|
|