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.
@@ -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| make_put 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 make_put(*args)
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
- htable.delete specs.map { |spec| spec.empty? ? nil : make_delete(*spec) }.compact
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
- htable.delete rowkeys.map { |rk| Delete.new(Util.to_bytes rk) }
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 [Fixnum] Column value after increment
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
- rowkey.each do |key, spec|
162
- increment key, spec
163
- end
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
- col, by = args
174
- cf, cq = lookup_and_parse col
175
- htable.incrementColumnValue Util.to_bytes(rowkey), cf, cq, by || 1
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
- def make_put rowkey, props
232
- Put.new(Util.to_bytes rowkey).tap { |put|
233
- props.each do |col, val|
234
- next if val.nil?
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
- raise ArgumentError, "no column to put" if put.empty?
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
 
@@ -1,5 +1,5 @@
1
1
  class HBase
2
2
  module JRuby
3
- VERSION = '0.3.5'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
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 'hbase.zookeeper.quorum' => ZK
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?
@@ -142,4 +142,8 @@ class TestByteArray < Test::Unit::TestCase
142
142
  assert_equal "Hello", ba.shift(:string, 5)
143
143
  assert_equal 3.14, ba.shift(:float)
144
144
  end
145
+
146
+ def test_to_s
147
+ assert_equal 'hello', HBase::ByteArray['hello'].to_s
148
+ end
145
149
  end
data/test/test_schema.rb CHANGED
@@ -52,17 +52,19 @@ class TestSchema < TestHBaseJRubyBase
52
52
  }
53
53
 
54
54
  # PUT
55
- @table.put 1, 'cf1:a' => data[:a], 'cf1:b' => data[:b], 'cf1:c' => data[:c],
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 2, data
60
+ @table.put rk2, data
59
61
 
60
62
  # GET
61
- row = @table.get(2)
62
- assert_equal Set[ *@table.get(1).to_h.values.map { |b| HBase::ByteArray.new b }],
63
- Set[ * row.to_h.values.map { |b| HBase::ByteArray.new b }]
64
- assert_equal Set[ *@table.get(1).to_h.keys ], Set[ *row.to_h.keys ]
65
- assert_equal Set[ *data.keys ], Set[ *row.to_h.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(1).to_h
89
+ data1 = @table.get(rk1).to_h
88
90
  data1[:a] *= 2
89
91
  data1[:b] = :new_symbol
90
- @table.put 3, data1
91
- @table.increment 3, :a => 5
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, @table.get(3)[:a]
95
- assert_equal :new_symbol, @table.get(3)[:b]
96
- assert_equal :new_symbol, @table.get(3)['b']
97
- assert_equal :new_symbol, @table.get(3)['cf1:b']
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 3, :g => 3.14
114
- assert_equal 3.14, @table.get(3)[:g]
115
- @table.put 3, :g => 314
116
- assert_equal 314, @table.get(3)[:g]
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
- @table.put 4, :g => 3.14, 'cf2:g' => 'String'
120
- assert_equal 3.14, @table.get(4)[:g]
121
- assert_equal 'String', @table.get(4)['cf2:g'].to_s
122
- assert_equal 3.14, @table.get(4).to_h[:g]
123
- assert_equal 'String', @table.get(4).to_h['cf2:g'].to_s
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
- @table.put(100 => data)
161
+ rk = next_rowkey
162
+ @table.put(rk => data)
156
163
 
157
- john = @table.get(100)
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 1, data
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 1
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
- assert_equal 1890, table.range(0..100).first[:year]
233
- assert_equal 2, table.range(0..100).first.raw(:year).length
234
- assert_equal 1, table.range(0..100).filter(:year => 1890).to_a.length
235
- assert_equal 1, table.range(0..100).filter(:year => 1890).count
236
- assert_equal 1, table.range(0..100).filter(:year => 1880...1900).count
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
- table.range(0..100).
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, :reviews => 1, :stars => 5
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(1)[:price]
262
- assert_equal data[:reviews] + 1, table.get(1)[:reviews]
263
- assert_equal data[:stars] + 5, table.get(1)[:stars]
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 2, :reviews => 100, :stars => 500
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 1, 'cf1:x' => 1000
274
- table.put 1, [:cf1, :y] => 2000
275
- table.put 1, [:cf1, 2013] => 3000
276
- assert_equal 1000, table.get(1).fixnum('cf1:x')
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(1)[param])
288
- assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(1)[*param])
289
- assert_equal 1000, HBase::Util.from_bytes(:fixnum, table.get(1).to_h[param])
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(1)[:cf1, :y])
293
- assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(1)[:cf1, 2013])
294
- assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(1)[[:cf1, 2013]])
295
- assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(1).to_h[[:cf1, HBase::ByteArray[2013]]])
296
- assert_equal 3000, HBase::Util.from_bytes(:fixnum, table.get(1).to_h[[:cf1, 2013]])
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 1, :title
300
- assert_equal nil, table.get(1)[:title]
301
- assert_equal data[:author], table.get(1)[:author]
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 1, :cf1
305
- assert_equal nil, table.get(1)[:author]
306
- assert_equal data[:summary], table.get(1)[:summary]
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 1
310
- assert_equal nil, table.get(1)
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 1, :a => nil, :b => nil, :c => nil, 'cf1:z' => nil
382
+ @table.put rk, :a => nil, :b => nil, :c => nil, 'cf1:z' => nil
328
383
  }
329
- @table.put 1, :a => nil, :b => nil, :c => nil, :d => 'yo', 'cf1:z' => 1000
330
- h = @table.get(1).to_h
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
- @table.put 1, :a => 100
349
- assert_equal 100, @table.get(1)[:a]
350
- assert_equal 100, @table.get(1)['cf1:a']
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
- assert_equal nil, @table.get(1)[:a]
354
- assert_equal true, HBase::Util.java_bytes?(@table.get(1)['cf1:a'])
355
- assert_equal 100, HBase::Util.from_bytes(:fixnum, @table.get(1)['cf1:a'])
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