hbase-jruby 0.3.5-java → 0.4.0-java

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.
@@ -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