hbase-jruby 0.1.4-java → 0.1.5-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.
@@ -1,6 +1,11 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.1.5
5
+ -----
6
+ - Added support for shorter integers
7
+ - Extended `HBase::ByteArray` for easy manipulation of Java byte arrays
8
+
4
9
  0.1.4
5
10
  -----
6
11
  - Fix: Start/stop row not correctly set when byte array rowkey range specified
data/README.md CHANGED
@@ -65,9 +65,9 @@ Apache Maven is the de facto standard dependency management mechanism for Java p
65
65
  Current version of *hbase-jruby* is shipped with Maven dependency specifications
66
66
  for the following Hadoop/HBase distributions.
67
67
 
68
- * cdh4.1.2
68
+ * [cdh4.1.2](https://github.com/junegunn/hbase-jruby/blob/master/lib/hbase-jruby/pom/cdh4.1.2.xml)
69
69
  * Recommended as of now
70
- * cdh3u5
70
+ * [cdh3u5](https://github.com/junegunn/hbase-jruby/blob/master/lib/hbase-jruby/pom/cdh3u5.xml)
71
71
  * Does not support some features
72
72
 
73
73
  ```ruby
@@ -635,6 +635,87 @@ table.get('rowkey').string(HBase::ColumnKey(:cf1, 100))
635
635
  # ...
636
636
  ```
637
637
 
638
+ ### Shorter integers
639
+
640
+ A Ruby Fixnum is an 8-byte integer, which is equivalent `long` type in Java.
641
+ When you want to use shorter integer types such as int, short, or byte,
642
+ you can then use the special Hash representation of integers.
643
+
644
+ ```ruby
645
+ # 4-byte int value as the rowkey
646
+ table.put({ int: 12345 }, 'cf1:a' => { byte: 100 }, # 1-byte integer
647
+ 'cf1:b' => { short: 200 }, # 2-byte integer
648
+ 'cf1:c' => { int: 300 }, # 4-byte integer
649
+ 'cf1:4' => 400) # Ordinary 8-byte integer
650
+
651
+ result = table.get(int: 12345)
652
+
653
+ result.byte('cf1:a') # 100
654
+ result.short('cf1:b') # 200
655
+ result.int('cf1:c') # 300
656
+ # ...
657
+ ```
658
+
659
+ ### Working with byte arrays
660
+
661
+ In HBase, virtually everything is stored as a byte array.
662
+ Although *hbase-jruby* tries hard to hide the fact,
663
+ at some point you may need to get your hands dirty with native Java byte arrays.
664
+ For example, it's [a common practice] [1] to use a composite row key,
665
+ which is a concatenation of several components of different types.
666
+
667
+ [1]: http://blog.sematext.com/2012/08/09/consider-using-fuzzyrowfilter-when-in-need-for-secondary-indexes-in-hbase/
668
+
669
+ `HBase::ByteArray` is a boxed class for native Java byte arrays,
670
+ which makes byte array manipulation much easier.
671
+
672
+ A ByteArray can be created as a concatenation of any number of objects.
673
+
674
+ ```ruby
675
+ ba = HBase::ByteArray(100, 3.14, {int: 300}, "Hello World")
676
+ ```
677
+
678
+ Then you can slice it and decode each part,
679
+
680
+ ```ruby
681
+ # Slicing
682
+ first = ba[0, 8]
683
+ second = ba[8...16]
684
+
685
+ first.decode(:fixnum) # 100
686
+ second.decode(:float) # 3.14
687
+ ```
688
+
689
+ append, prepend more elements to it,
690
+
691
+ ```ruby
692
+ ba.unshift 200, true
693
+ ba << { short: 300 }
694
+ ```
695
+
696
+ concatenate another ByteArray,
697
+
698
+ ```ruby
699
+ ba += HBase::ByteArray(1024)
700
+ ```
701
+
702
+ or shift decoded objects from it.
703
+
704
+ ```ruby
705
+ ba.shift(:fixnum)
706
+ ba.shift(:boolean)
707
+ ba.shift(:fixnum)
708
+ ba.shift(:float)
709
+ ba.shift(:int)
710
+ ba.shift(:string, 11) # Byte length must be given as Strings are not fixed in size
711
+ ```
712
+
713
+ `ByteArray#java` method returns the underlying native Java byte array.
714
+
715
+ ```ruby
716
+ ba.java # Returns the native Java byte array (byte[])
717
+ ```
718
+
638
719
  ### Table administration
639
720
 
640
721
  `HBase#Table` provides a few *synchronous* table administration methods.
@@ -15,3 +15,4 @@ require "hbase-jruby/table"
15
15
  require "hbase-jruby/result"
16
16
  require 'hbase-jruby/hbase'
17
17
 
18
+ HBase.import_java_classes!
@@ -1,20 +1,36 @@
1
1
  class HBase
2
2
  class << self
3
3
  # Shortcut method to HBase::ByteArray.new
4
- # @param [Object] value
5
- def ByteArray value
6
- ByteArray.new value
4
+ # @param [*Object] values
5
+ def ByteArray *values
6
+ ByteArray.new *values
7
7
  end
8
8
  end
9
9
  # Boxed class for Java byte arrays
10
10
  # @!attribute [r] java
11
- # @return [byte[]] Java byte array
11
+ # @return [byte[]] The underlying native Java byte array
12
12
  class ByteArray
13
13
  attr_reader :java
14
+ alias to_java java
15
+ alias to_java_bytes java
14
16
 
15
- # @param [Object] value
16
- def initialize value
17
- @java = Util.to_bytes value
17
+ include Enumerable
18
+
19
+ # Initializes ByteArray instance with the given objects,
20
+ # each converted to its byte array representation
21
+ # @param [*Object] values
22
+ def initialize *values
23
+ @java = values.inject(Util::JAVA_BYTE_ARRAY_EMPTY) { |sum, value|
24
+ Bytes.add sum, Util.to_bytes(value)
25
+ }
26
+ end
27
+
28
+ def each
29
+ if block_given?
30
+ @java.to_a.each { |byte| yield byte }
31
+ else
32
+ self
33
+ end
18
34
  end
19
35
 
20
36
  # Checks if the two byte arrays are the same
@@ -31,15 +47,77 @@ class ByteArray
31
47
  end
32
48
 
33
49
  # Concats two byte arrays
34
- # @param [HBase::ByteArray] other
50
+ # @param [Object] other
35
51
  def + other
36
- ByteArray.new(Bytes.add @java, other.java)
52
+ ByteArray.new(@java, other)
37
53
  end
38
54
 
39
- # Returns the Java byte array
40
- # @return [byte[]]
41
- def to_java_bytes
42
- @java
55
+ # Appends the byte array of the given object on to the end
56
+ # @param [Object] other
57
+ # @return [ByteArray] Modified self
58
+ def << other
59
+ @java = Bytes.add @java, Util.to_bytes(other)
60
+ self
61
+ end
62
+
63
+ # Prepends the byte array of the given object to the front
64
+ # @param [*Object] args Objects to prepend
65
+ # @return [ByteArray] Modified self
66
+ def unshift *args
67
+ @java = (ByteArray.new(*args) + self).java
68
+ self
69
+ end
70
+
71
+ # Returns the length of the byte array
72
+ # @return [Fixnum]
73
+ def length
74
+ @java.length
75
+ end
76
+
77
+ # Slices the byte array
78
+ # @param [Object] index
79
+ # @return [ByteArray]
80
+ def [] *index
81
+ if index.length == 1 && index.first.is_a?(Fixnum)
82
+ @java.to_a[*index]
83
+ else
84
+ ByteArray.new(@java.to_a[*index].to_java(Java::byte))
85
+ end
86
+ end
87
+
88
+ # @param [Symbol] type
89
+ # @return [Object]
90
+ def decode type
91
+ Util.from_bytes type, @java
92
+ end
93
+
94
+ # Returns the first element decoded as the given type
95
+ # and removes the portion from the byte array.
96
+ # For types of variable lengths, such as :string and :bigdecimal, byte size must be given.
97
+ # @param [Symbol] type
98
+ # @return [Object]
99
+ def shift type, length = nil
100
+ length =
101
+ case type
102
+ when :fixnum, :long, :float, :double
103
+ 8
104
+ when :int
105
+ 4
106
+ when :short
107
+ 2
108
+ when :boolean, :bool, :byte
109
+ 1
110
+ else
111
+ length
112
+ end
113
+ raise ArgumentError.new("Byte length must be specified for type: #{type}") unless length
114
+ raise ArgumentError.new("Not enought bytes for #{type}") if length > @java.length
115
+
116
+ arr = @java.to_a
117
+ val = arr[0, length].to_java(Java::byte)
118
+ @java = arr[length..-1].to_java(Java::byte)
119
+
120
+ Util.from_bytes type, val
43
121
  end
44
122
 
45
123
  # Returns the first byte array whose prefix doesn't match this byte array
@@ -14,7 +14,7 @@ class Cell
14
14
 
15
15
  # Returns the rowkey of the cell decoded as the given type
16
16
  # @param [Symbol] type The type of the rowkey.
17
- # Can be one of :string, :symbol, :fixnum, :float, :bigdecimal, :boolean and :raw.
17
+ # Can be one of :string, :symbol, :fixnum, :float, :short, :int, :bigdecimal, :boolean and :raw.
18
18
  # @return [String, byte[]]
19
19
  def rowkey type = :string
20
20
  Util.from_bytes type, @java.getRow
@@ -35,7 +35,7 @@ class Cell
35
35
 
36
36
  # Returns the column qualifier of the cell
37
37
  # @param [Symbol] type The type of the qualifier.
38
- # Can be one of :string, :symbol, :fixnum, :float, :bigdecimal, :boolean and :raw.
38
+ # Can be one of :string, :symbol, :fixnum, :float, :short, :int, :bigdecimal, :boolean and :raw.
39
39
  # @return [Object]
40
40
  def qualifier type = :string
41
41
  Util.from_bytes type, @java.getQualifier
@@ -75,8 +75,7 @@ class Cell
75
75
  def fixnum
76
76
  Util.from_bytes :fixnum, value
77
77
  end
78
- alias integer fixnum
79
- alias int fixnum
78
+ alias long fixnum
80
79
 
81
80
  # Returns the column value as a BigDecimal
82
81
  # @return [BigDecimal]
@@ -40,7 +40,7 @@ class HBase
40
40
  f << xml
41
41
  end
42
42
  rescue OpenURI::HTTPError => e
43
- # No such distribution anywhere
43
+ # No such distribution anywhere. Leave path to be nil.
44
44
  end
45
45
  end
46
46
 
@@ -57,15 +57,105 @@ class HBase
57
57
  end
58
58
 
59
59
  # Load jars
60
- jars_loaded = jars.select { |jar| File.exists?(jar) && File.extname(jar) == '.jar' }.select do |jar|
61
- require jar
62
- end
60
+ jars_loaded = jars.select { |jar|
61
+ File.exists?(jar) &&
62
+ File.extname(jar) == '.jar' &&
63
+ require(jar)
64
+ }
63
65
 
64
- Util.import_java_classes!
66
+ # Try importing Java classes again
67
+ not_found = HBase.import_java_classes!
68
+ if verbose && !not_found.empty?
69
+ warn "Java classes not found: #{not_found.join(', ')}"
70
+ end
65
71
 
66
72
  return jars_loaded
67
73
  ensure
68
74
  tempfiles.each { |tempfile| tempfile.unlink rescue nil }
69
75
  end
70
- end
76
+
77
+ # Import Java classes (Prerequisite for classes in hbase-jruby)
78
+ # @return [Array<String>] List of Java classes not found
79
+ def import_java_classes!
80
+ imp = lambda { |hash|
81
+ hash.map { |base, classes|
82
+ base.class_eval do
83
+ classes.map { |klass|
84
+ begin
85
+ import klass
86
+ nil
87
+ rescue NameError => e
88
+ klass
89
+ end
90
+ }.compact
91
+ end
92
+ }.flatten
93
+ }
94
+
95
+ imp.call(
96
+ HBase => %w[
97
+ org.apache.hadoop.hbase.HBaseConfiguration
98
+ org.apache.hadoop.hbase.client.HBaseAdmin
99
+ org.apache.hadoop.hbase.client.HConnectionManager
100
+ org.apache.hadoop.hbase.client.HTablePool
101
+ ],
102
+ HBase::Util => %w[
103
+ java.nio.ByteBuffer
104
+ org.apache.hadoop.hbase.KeyValue
105
+ org.apache.hadoop.hbase.util.Bytes
106
+ ],
107
+ HBase::ByteArray => %w[
108
+ java.util.Arrays
109
+ org.apache.hadoop.hbase.util.Bytes
110
+ ],
111
+ HBase::Cell => %w[
112
+ org.apache.hadoop.hbase.KeyValue
113
+ ],
114
+ HBase::Result => %w[
115
+ org.apache.hadoop.hbase.util.Bytes
116
+ ],
117
+ HBase::ColumnKey => %w[
118
+ java.util.Arrays
119
+ org.apache.hadoop.hbase.util.Bytes
120
+ ],
121
+ HBase::Table => %w[
122
+ org.apache.hadoop.hbase.HColumnDescriptor
123
+ org.apache.hadoop.hbase.HTableDescriptor
124
+ org.apache.hadoop.hbase.client.Delete
125
+ org.apache.hadoop.hbase.client.Increment
126
+ org.apache.hadoop.hbase.client.Put
127
+ org.apache.hadoop.hbase.io.hfile.Compression
128
+ org.apache.hadoop.hbase.regionserver.StoreFile
129
+ ],
130
+ HBase::Scoped => %w[
131
+ org.apache.hadoop.hbase.client.Get
132
+ org.apache.hadoop.hbase.client.Scan
133
+ org.apache.hadoop.hbase.filter.BinaryComparator
134
+ org.apache.hadoop.hbase.filter.ColumnPaginationFilter
135
+ org.apache.hadoop.hbase.filter.ColumnRangeFilter
136
+ org.apache.hadoop.hbase.filter.CompareFilter
137
+ org.apache.hadoop.hbase.filter.FilterBase
138
+ org.apache.hadoop.hbase.filter.FilterList
139
+ org.apache.hadoop.hbase.filter.KeyOnlyFilter
140
+ org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter
141
+ org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter
142
+ org.apache.hadoop.hbase.filter.PrefixFilter
143
+ org.apache.hadoop.hbase.filter.RegexStringComparator
144
+ org.apache.hadoop.hbase.filter.RowFilter
145
+ org.apache.hadoop.hbase.filter.SingleColumnValueFilter
146
+ org.apache.hadoop.hbase.filter.WhileMatchFilter
147
+ org.apache.hadoop.hbase.client.coprocessor.AggregationClient
148
+ org.apache.hadoop.hbase.client.coprocessor.LongColumnInterpreter
149
+ ]).tap { |not_found|
150
+
151
+ if not_found.empty?
152
+ self.instance_eval do
153
+ def import_java_classes!
154
+ []
155
+ end
156
+ end
157
+ end
158
+ }
159
+ end
160
+ end#class << self
71
161
  end
@@ -11,7 +11,7 @@ class HBase
11
11
  # Connects to HBase
12
12
  # @param [Hash] config A key-value pairs to build HBaseConfiguration from
13
13
  def initialize config = {}
14
- Util.import_java_classes!
14
+ HBase.import_java_classes!
15
15
 
16
16
  @config =
17
17
  case config
@@ -8,7 +8,7 @@ class Result
8
8
 
9
9
  # Returns the rowkey of the row
10
10
  # @param [Symbol] type The type of the rowkey
11
- # Can be one of :string, :symbol, :fixnum, :float, :bigdecimal, :boolean and :raw.
11
+ # Can be one of :string, :symbol, :fixnum, :float, :short, :int, :bigdecimal, :boolean and :raw.
12
12
  # @return [String, byte[]]
13
13
  def rowkey type = :string
14
14
  Util.from_bytes type, @result.getRow
@@ -168,37 +168,119 @@ class Result
168
168
  end
169
169
  alias syms symbols
170
170
 
171
- # Returns column values as Fixnums
172
- # @overload fixnum(column)
171
+ # Returns 1-byte column values as Fixnums
172
+ # @overload byte(column)
173
173
  # Returns the latest column value as a Fixnum
174
174
  # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
175
175
  # @return [Fixnum]
176
+ # @overload byte(columns)
177
+ # For each column specified,
178
+ # returns the latest 1-byte column values as a Fixnum
179
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
180
+ # @return [Array<Fixnum>]
181
+ def byte cols
182
+ decode_values :byte, cols
183
+ end
184
+
185
+ # Returns all versions of 1-byte column values as Fixnums in a Hash indexed by their timestamps
186
+ # @overload bytes(column)
187
+ # Returns all versions of column values as Fixnums in a Hash indexed by their timestamps
188
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
189
+ # @return [Hash<Fixnum, Fixnum>]
190
+ # @overload bytes(columns)
191
+ # For each column specified,
192
+ # returns all versions of 1-byte column values as Fixnums in a Hash indexed by their timestamps
193
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
194
+ # @return [Array<Hash<Fixnum, Fixnum>>]
195
+ def bytes cols
196
+ decode_values :byte, cols, true
197
+ end
198
+
199
+ # Returns 2-byte column values as Fixnums
200
+ # @overload short(column)
201
+ # Returns the latest 2-byte column value as a Fixnum
202
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
203
+ # @return [Fixnum]
204
+ # @overload short(columns)
205
+ # For each column specified,
206
+ # returns the latest 2-byte column values as a Fixnum
207
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
208
+ # @return [Array<Fixnum>]
209
+ def short cols
210
+ decode_values :short, cols
211
+ end
212
+
213
+ # Returns all versions of 2-byte column values as Fixnums in a Hash indexed by their timestamps
214
+ # @overload shorts(column)
215
+ # Returns all versions of 2-byte column values as Fixnums in a Hash indexed by their timestamps
216
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
217
+ # @return [Hash<Fixnum, Fixnum>]
218
+ # @overload shorts(columns)
219
+ # For each column specified,
220
+ # returns all versions of 2-byte column values as Fixnums in a Hash indexed by their timestamps
221
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
222
+ # @return [Array<Hash<Fixnum, Fixnum>>]
223
+ def shorts cols
224
+ decode_values :short, cols, true
225
+ end
226
+
227
+ # Returns 4-byte column values as Fixnums
228
+ # @overload int(column)
229
+ # Returns the latest 4-byte column value as a Fixnum
230
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
231
+ # @return [Fixnum]
232
+ # @overload int(columns)
233
+ # For each column specified,
234
+ # returns the latest 4-byte column values as a Fixnum
235
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
236
+ # @return [Array<Fixnum>]
237
+ def int cols
238
+ decode_values :int, cols
239
+ end
240
+
241
+ # Returns all versions of 4-byte column values as Fixnums in a Hash indexed by their timestamps
242
+ # @overload ints(column)
243
+ # Returns all versions of 4-byte column values as Fixnums in a Hash indexed by their timestamps
244
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
245
+ # @return [Hash<Fixnum, Fixnum>]
246
+ # @overload ints(columns)
247
+ # For each column specified,
248
+ # returns all versions of 4-byte column values as Fixnums in a Hash indexed by their timestamps
249
+ # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
250
+ # @return [Array<Hash<Fixnum, Fixnum>>]
251
+ def ints cols
252
+ decode_values :int, cols, true
253
+ end
254
+
255
+ # Returns 8-byte column values as Fixnums
256
+ # @overload fixnum(column)
257
+ # Returns the latest 8-byte column value as a Fixnum
258
+ # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
259
+ # @return [Fixnum]
176
260
  # @overload fixnum(columns)
177
261
  # For each column specified,
178
- # returns the latest column values as a Fixnum
262
+ # returns the latest 8-byte column values as a Fixnum
179
263
  # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
180
264
  # @return [Array<Fixnum>]
181
265
  def fixnum cols
182
266
  decode_values :fixnum, cols
183
267
  end
184
- alias integer fixnum
185
- alias int fixnum
268
+ alias long fixnum
186
269
 
187
- # Returns all versions of column values as Fixnums in a Hash indexed by their timestamps
270
+ # Returns all versions of 8-byte column values as Fixnums in a Hash indexed by their timestamps
188
271
  # @overload fixnums(column)
189
- # Returns all versions of column values as Fixnums in a Hash indexed by their timestamps
272
+ # Returns all versions of 8-byte column values as Fixnums in a Hash indexed by their timestamps
190
273
  # @param [String, HBase::ColumnKey] column "FAMILY:QUALIFIER" expression or ColumnKey object.
191
274
  # @return [Hash<Fixnum, Fixnum>]
192
275
  # @overload fixnums(columns)
193
276
  # For each column specified,
194
- # returns all versions of column values as Fixnums in a Hash indexed by their timestamps
277
+ # returns all versions of 8-byte column values as Fixnums in a Hash indexed by their timestamps
195
278
  # @param [Array<String|HBase::ColumnKey>] columns Array of "FAMILY:QUALIFIER" expressions and ColumnKey objects.
196
279
  # @return [Array<Hash<Fixnum, Fixnum>>]
197
280
  def fixnums cols
198
281
  decode_values :fixnum, cols, true
199
282
  end
200
- alias integers fixnums
201
- alias ints fixnums
283
+ alias longs fixnums
202
284
 
203
285
  # Returns column values as Bigdecimals
204
286
  # @overload bigdecimal(column)
@@ -34,7 +34,7 @@ private
34
34
 
35
35
  def column_interpreter_for type
36
36
  case type
37
- when :fixnum, :int, :integer
37
+ when :fixnum, :long
38
38
  LongColumnInterpreter.new
39
39
  when org.apache.hadoop.hbase.coprocessor.ColumnInterpreter
40
40
  type
@@ -421,8 +421,15 @@ private
421
421
  cf, cq = Util.parse_column_name(col)
422
422
  case val
423
423
  when Hash
424
- val.each do |ts, v|
425
- put.add cf, cq, ts, Util.to_bytes(v)
424
+ val.each do |t, v|
425
+ case t
426
+ # Timestamp
427
+ when Fixnum
428
+ put.add cf, cq, t, Util.to_bytes(v)
429
+ # Types: :byte, :short, :int, ...
430
+ else
431
+ put.add cf, cq, Util.to_bytes(t => v)
432
+ end
426
433
  end
427
434
  else
428
435
  put.add cf, cq, Util.to_bytes(val)
@@ -33,6 +33,25 @@ module Util
33
33
  Bytes.java_send :toBytes, [java.math.BigDecimal], v.to_java
34
34
  when java.math.BigDecimal
35
35
  Bytes.java_send :toBytes, [java.math.BigDecimal], v
36
+ when Hash
37
+ len = v.length
38
+ raise ArgumentError, "Unknown value format" unless len == 1
39
+
40
+ val = v.values.first
41
+ raise ArgumentError, "Unknown value format" unless val.is_a?(Fixnum)
42
+
43
+ case v.keys.first
44
+ when :byte
45
+ [val].to_java(Java::byte)
46
+ when :int
47
+ Bytes.java_send :toBytes, [Java::int], val
48
+ when :short
49
+ Bytes.java_send :toBytes, [Java::short], val
50
+ when :long, :fixnum
51
+ Bytes.java_send :toBytes, [Java::long], val
52
+ else
53
+ raise ArgumentError, "Invalid value format"
54
+ end
36
55
  else
37
56
  if java_bytes?(v)
38
57
  v
@@ -52,8 +71,14 @@ module Util
52
71
  case type
53
72
  when :string, :str
54
73
  Bytes.to_string val
55
- when :fixnum, :int, :integer
74
+ when :fixnum, :long
56
75
  Bytes.to_long val
76
+ when :byte
77
+ val.first
78
+ when :int
79
+ Bytes.to_int val
80
+ when :short
81
+ Bytes.to_short val
57
82
  when :symbol, :sym
58
83
  Bytes.to_string(val).to_sym
59
84
  when :bigdecimal
@@ -97,89 +122,6 @@ module Util
97
122
  return cf, cq
98
123
  end
99
124
  end
100
-
101
- # Import Java classes (Prerequisite for classes in hbase-jruby)
102
- # @return [nil]
103
- def import_java_classes!
104
- imp = lambda { |base, classes|
105
- base.class_eval do
106
- classes.each do |klass|
107
- begin
108
- import klass
109
- rescue NameError => e
110
- warn e
111
- end
112
- end
113
- end
114
- }
115
-
116
- @@imported ||= begin
117
- imp.call HBase, %w[
118
- org.apache.hadoop.hbase.HBaseConfiguration
119
- org.apache.hadoop.hbase.client.HBaseAdmin
120
- org.apache.hadoop.hbase.client.HTablePool
121
- org.apache.hadoop.hbase.client.HConnectionManager
122
- ]
123
-
124
- imp.call HBase::Util, %w[
125
- java.nio.ByteBuffer
126
- org.apache.hadoop.hbase.util.Bytes
127
- org.apache.hadoop.hbase.KeyValue
128
- ]
129
-
130
- imp.call HBase::ByteArray, %w[
131
- java.util.Arrays
132
- org.apache.hadoop.hbase.util.Bytes
133
- ]
134
-
135
- imp.call HBase::Cell, %w[
136
- org.apache.hadoop.hbase.KeyValue
137
- ]
138
-
139
- imp.call HBase::Result, %w[
140
- org.apache.hadoop.hbase.util.Bytes
141
- ]
142
-
143
- imp.call HBase::ColumnKey, %w[
144
- java.util.Arrays
145
- org.apache.hadoop.hbase.util.Bytes
146
- ]
147
-
148
- imp.call HBase::Table, %w[
149
- org.apache.hadoop.hbase.HColumnDescriptor
150
- org.apache.hadoop.hbase.HTableDescriptor
151
- org.apache.hadoop.hbase.client.Delete
152
- org.apache.hadoop.hbase.client.Increment
153
- org.apache.hadoop.hbase.client.Put
154
- org.apache.hadoop.hbase.io.hfile.Compression
155
- org.apache.hadoop.hbase.regionserver.StoreFile
156
- org.apache.hadoop.hbase.Coprocessor
157
- ]
158
-
159
- imp.call HBase::Scoped, %w[
160
- org.apache.hadoop.hbase.client.Get
161
- org.apache.hadoop.hbase.client.Scan
162
- org.apache.hadoop.hbase.filter.BinaryComparator
163
- org.apache.hadoop.hbase.filter.ColumnPaginationFilter
164
- org.apache.hadoop.hbase.filter.ColumnRangeFilter
165
- org.apache.hadoop.hbase.filter.CompareFilter
166
- org.apache.hadoop.hbase.filter.FilterBase
167
- org.apache.hadoop.hbase.filter.FilterList
168
- org.apache.hadoop.hbase.filter.KeyOnlyFilter
169
- org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter
170
- org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter
171
- org.apache.hadoop.hbase.filter.PrefixFilter
172
- org.apache.hadoop.hbase.filter.RegexStringComparator
173
- org.apache.hadoop.hbase.filter.RowFilter
174
- org.apache.hadoop.hbase.filter.SingleColumnValueFilter
175
- org.apache.hadoop.hbase.filter.WhileMatchFilter
176
- org.apache.hadoop.hbase.client.coprocessor.AggregationClient
177
- org.apache.hadoop.hbase.client.coprocessor.LongColumnInterpreter
178
- ]
179
- end
180
-
181
- nil
182
- end
183
125
  end
184
126
  end#Util
185
127
  end#HBase
@@ -1,5 +1,5 @@
1
1
  class HBase
2
2
  module JRuby
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
5
5
  end
@@ -13,7 +13,7 @@ class TestAggregation < TestHBaseJRubyBase
13
13
  assert_nil @table.enable_aggregation! # no prob!
14
14
 
15
15
  lci = org.apache.hadoop.hbase.client.coprocessor.LongColumnInterpreter.new
16
- [nil, :fixnum, :int, :integer, lci].each do |ci|
16
+ [nil, :fixnum, :long, lci].each do |ci|
17
17
  assert_equal 100, @table.project('cf1:a').aggregate(:row_count, *[*ci].compact)
18
18
  assert_equal 5050, @table.project('cf1:a').aggregate(:sum, *[*ci].compact)
19
19
  assert_equal 1, @table.project('cf1:a').aggregate(:min, *[*ci].compact)
@@ -45,5 +45,101 @@ class TestByteArray < Test::Unit::TestCase
45
45
 
46
46
  assert_equal 100, HBase::Util.from_bytes( :fixnum, concat.to_java_bytes.to_a[0, 8].to_java(Java::byte) )
47
47
  assert_equal 200, HBase::Util.from_bytes( :fixnum, concat.java.to_a[8, 8].to_java(Java::byte) )
48
+
49
+ assert HBase::ByteArray(100, 200).eql?(concat)
50
+ assert concat.eql?(HBase::ByteArray(100) + 200)
51
+ assert concat.eql?(HBase::ByteArray(100) << 200)
52
+
53
+ ba = HBase::ByteArray(100)
54
+ ba += HBase::ByteArray(200)
55
+ assert_equal concat, ba
56
+ end
57
+
58
+ def test_default_constructor
59
+ assert_equal 0, HBase::ByteArray().java.to_a.length
60
+ assert_equal 0, HBase::ByteArray.new.java.to_a.length
61
+ end
62
+
63
+ def test_slice
64
+ ba = HBase::ByteArray(100, 200, "Hello", 3.14)
65
+
66
+ assert_equal 100, ba[0, 8].decode(:fixnum)
67
+ assert_equal 200, ba[8...16].decode(:fixnum)
68
+ assert_equal "Hello", ba[16, 5].decode(:string)
69
+ assert_equal 3.14, ba[21..-1].decode(:float)
70
+ assert_equal "H", ba[16].chr
71
+ end
72
+
73
+ def test_length_shift
74
+ ba = HBase::ByteArray(100, 200, "Hello", false, 3.14)
75
+
76
+ assert_equal 30, ba.length
77
+ assert_equal 100, ba.shift(:fixnum)
78
+ assert_equal 22, ba.length
79
+ assert_equal 200, ba.shift(:fixnum)
80
+ assert_equal 14, ba.length
81
+ assert_raise(ArgumentError) { ba.shift(:string) }
82
+ assert_equal "Hello", ba.shift(:string, 5)
83
+ assert_equal 9, ba.length
84
+ assert_equal false, ba.shift(:boolean)
85
+ assert_equal 8, ba.length
86
+ assert_equal 3.14, ba.shift(:float)
87
+ assert_equal 0, ba.length
88
+
89
+ assert_raise(ArgumentError) { ba.shift(:fixnum) }
90
+ end
91
+
92
+ def test_short_int
93
+ assert_equal 1, HBase::ByteArray(:byte => 12).length
94
+ assert_equal 12, HBase::ByteArray(:byte => 12).decode(:byte)
95
+ assert_raise(RangeError) { HBase::ByteArray(:byte => 128) }
96
+
97
+ assert_equal 2, HBase::ByteArray(:short => 12345).length
98
+ assert_equal 12345, HBase::ByteArray(:short => 12345).decode(:short)
99
+ assert_raise(RangeError) { HBase::ByteArray( :short => 1 << 16 ) }
100
+
101
+ assert_equal 4, HBase::ByteArray(:int => 12345).length
102
+ assert_equal 12345, HBase::ByteArray(:int => 12345).decode(:int)
103
+ assert_raise(RangeError) { HBase::ByteArray.new( :int => 1 << 32 ) }
104
+
105
+ ba = HBase::ByteArray( {:int => 10000}, 20000, {:short => 30000}, "Hello" )
106
+ assert_equal 10000, ba[0, 4].decode(:int)
107
+ assert_equal 20000, ba[4, 8].decode(:long)
108
+ assert_equal 30000, ba[12, 2].decode(:short)
109
+ assert_equal "Hell", ba[14, 4].decode(:string)
110
+ end
111
+
112
+ def test_each
113
+ ba = HBase::ByteArray("Hello world")
114
+ Hash[ba.to_a.zip("Hello world".each_char.to_a)].each do |ord, chr|
115
+ assert_equal ord.chr, chr
116
+ end
117
+ end
118
+
119
+ def test_unshift
120
+ bd = BigDecimal.new("123456789012345678901234567890")
121
+ ba = HBase::ByteArray(bd)
122
+ oid = ba.object_id
123
+ assert_equal oid, ba.unshift(:short => 1000).object_id
124
+
125
+ ba.unshift("a", "b", "c")
126
+ assert_equal 'a', ba[0].chr
127
+ assert_equal 'b', ba[1].chr
128
+ assert_equal 'c', ba[2].chr
129
+ assert_equal 1000, ba[3, 2].decode(:short)
130
+ assert_equal bd, ba[5..-1].decode(:bigdecimal)
131
+ end
132
+
133
+ def test_append
134
+ ba = HBase::ByteArray()
135
+ oid = ba.object_id
136
+ assert_equal oid, (ba << 100).object_id
137
+
138
+ ba << 200 << {:int => 300} << "Hello" << 3.14
139
+ assert_equal 100, ba.shift(:fixnum)
140
+ assert_equal 200, ba.shift(:long)
141
+ assert_equal 300, ba.shift(:int)
142
+ assert_equal "Hello", ba.shift(:string, 5)
143
+ assert_equal 3.14, ba.shift(:float)
48
144
  end
49
145
  end
@@ -181,7 +181,7 @@ class TestScoped < TestHBaseJRubyBase
181
181
  @table.put rk, 'cf1:a' => rk
182
182
  end
183
183
  assert_equal 9, @table.range(1..9).count
184
- assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9], @table.range(1..9).map { |row| row.rowkey :integer }
184
+ assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9], @table.range(1..9).map { |row| row.rowkey :fixnum }
185
185
  assert_equal 8, @table.range(1...9).count
186
186
 
187
187
  @table.truncate!
@@ -201,17 +201,17 @@ class TestScoped < TestHBaseJRubyBase
201
201
  @table.put i.to_s, data
202
202
  end
203
203
 
204
- assert_equal [1, 2, 3], @table.range(1..3).map { |r| r.rowkey :integer }
204
+ assert_equal [1, 2, 3], @table.range(1..3).map { |r| r.rowkey :fixnum }
205
205
  assert_equal %w[1 10 11 12 13 14 15 2 3], @table.range('1'..'3').map { |r| r.rowkey :string }
206
206
  end
207
207
 
208
208
  def test_non_string_column_name
209
209
  @table.put 'rowkey', Hash[ (1..20).map { |cq| [HBase::ColumnKey('cf1', cq), cq] } ]
210
210
 
211
- assert((1..20).all? { |cq| @table.get('rowkey').integer(HBase::ColumnKey('cf1', cq)) == cq })
211
+ assert((1..20).all? { |cq| @table.get('rowkey').fixnum(HBase::ColumnKey('cf1', cq)) == cq })
212
212
 
213
213
  assert @table.project(['cf1', 10], ['cf1', 20]).map { |r|
214
- [r.integer(HBase::ColumnKey('cf1', 10)), r.integer(HBase::ColumnKey.new('cf1', 20))]
214
+ [r.fixnum(HBase::ColumnKey('cf1', 10)), r.fixnum(HBase::ColumnKey.new('cf1', 20))]
215
215
  }.all? { |e| e == [10, 20] }
216
216
 
217
217
  hash = @table.get('rowkey').to_hash(
@@ -32,6 +32,9 @@ class TestScoped < TestHBaseJRubyBase
32
32
  'cf1:d' => false,
33
33
  'cf1:f' => :bol,
34
34
  'cf1:g' => BigDecimal.new("456.123"),
35
+ 'cf1:byte' => { :byte => 100 },
36
+ 'cf1:short' => { :short => 200 },
37
+ 'cf1:int' => { :int => 300 },
35
38
  'cf1:str1' => "Goodbye", 'cf1:str2' => "Cruel world")
36
39
  assert_equal 1, @table.put('row1',
37
40
  'cf1:a' => 1,
@@ -40,6 +43,10 @@ class TestScoped < TestHBaseJRubyBase
40
43
  'cf1:d' => true,
41
44
  'cf1:f' => :sym,
42
45
  'cf1:g' => BigDecimal.new("123.456"),
46
+ 'cf1:byte' => { :byte => 101 },
47
+ 'cf1:short' => { :short => 201 },
48
+ 'cf1:int' => { :int => 301 },
49
+ 'cf1:int2' => { :int => 401 },
43
50
  'cf1:str1' => "Hello", 'cf1:str2' => "World")
44
51
  # Batch put
45
52
  assert_equal 2, @table.put(
@@ -59,9 +66,13 @@ class TestScoped < TestHBaseJRubyBase
59
66
  assert_equal true, @table.get('row1').boolean('cf1:d')
60
67
  assert_equal :sym, @table.get('row1').symbol('cf1:f')
61
68
  assert_equal BigDecimal.new("123.456"), @table.get('row1').bigdecimal('cf1:g')
69
+ assert_equal 101, @table.get('row1').byte('cf1:byte')
70
+ assert_equal 201, @table.get('row1').short('cf1:short')
71
+ assert_equal 301, @table.get('row1').int('cf1:int')
62
72
 
63
73
  # single-get-multi-col
64
74
  assert_equal %w[Hello World], @table.get('row1').string(['cf1:str1', 'cf1:str2'])
75
+ assert_equal [301, 401], @table.get('row1').int(['cf1:int', 'cf1:int2'])
65
76
 
66
77
  # single-get-multi-ver
67
78
  assert_equal [1, 2], @table.get('row1').fixnums('cf1:a').values
@@ -73,6 +84,9 @@ class TestScoped < TestHBaseJRubyBase
73
84
  assert_equal [
74
85
  BigDecimal.new("123.456"),
75
86
  BigDecimal.new("456.123")], @table.get('row1').bigdecimals('cf1:g').values
87
+ assert_equal [101, 100], @table.get('row1').bytes('cf1:byte').values
88
+ assert_equal [201, 200], @table.get('row1').shorts('cf1:short').values
89
+ assert_equal [301, 300], @table.get('row1').ints('cf1:int').values
76
90
 
77
91
  assert @table.get('row1').fixnums('cf1:a').keys.all? { |k| k.instance_of? Fixnum }
78
92
 
@@ -83,13 +97,13 @@ class TestScoped < TestHBaseJRubyBase
83
97
 
84
98
  # multi-get
85
99
  assert_equal %w[row1 row2 row3], @table.get(['row1', 'row2', 'row3']).map { |r| r.rowkey }
86
- assert_equal [1, 2, 4 ], @table.get(['row1', 'row2', 'row3']).map { |r| r.integer('cf1:a') }
100
+ assert_equal [1, 2, 4 ], @table.get(['row1', 'row2', 'row3']).map { |r| r.fixnum('cf1:a') }
87
101
  assert_equal [3.14, 6.28, 6.28], @table.get(['row1', 'row2', 'row3']).map { |r| r.float('cf1:c') }
88
102
  assert_equal [nil, nil ], @table.get(['xxx', 'yyy'])
89
103
 
90
104
  # Unavailable columns
91
105
  assert_equal nil, @table.get('row1').symbol('cf1:xxx')
92
- assert_equal nil, @table.get('row1').integer('cf1:xxx')
106
+ assert_equal nil, @table.get('row1').fixnum('cf1:xxx')
93
107
 
94
108
  # Unavailable columns (plural form)
95
109
  assert_equal({}, @table.get('row1').strings('cf1:xxx'))
@@ -142,7 +156,7 @@ class TestScoped < TestHBaseJRubyBase
142
156
  }
143
157
  schema = {
144
158
  'cf1:a' => :string,
145
- 'cf1:b' => :integer,
159
+ 'cf1:b' => :fixnum,
146
160
  'cf1:c' => :float,
147
161
  HBase::ColumnKey(:cf2, :d) => :symbol,
148
162
  HBase::ColumnKey(:cf2, :e) => :boolean,
@@ -183,15 +197,15 @@ class TestScoped < TestHBaseJRubyBase
183
197
  assert_equal 1, @table.get('row1').fixnum('cf1:counter')
184
198
 
185
199
  @table.increment('row1', 'cf1:counter', 1)
186
- assert_equal 2, @table.get('row1').int('cf1:counter')
200
+ assert_equal 2, @table.get('row1').fixnum('cf1:counter')
187
201
 
188
202
  @table.increment('row1', 'cf1:counter', 2)
189
- assert_equal 4, @table.get('row1').integer('cf1:counter')
203
+ assert_equal 4, @table.get('row1').fixnum('cf1:counter')
190
204
 
191
205
  # Multi-column increment
192
206
  @table.increment('row1', 'cf1:counter' => 4, 'cf1:counter2' => 100)
193
- assert_equal 8, @table.get('row1').integer('cf1:counter')
194
- assert_equal 200, @table.get('row1').integer('cf1:counter2')
207
+ assert_equal 8, @table.get('row1').fixnum('cf1:counter')
208
+ assert_equal 200, @table.get('row1').fixnum('cf1:counter2')
195
209
  end
196
210
 
197
211
  def test_delete
@@ -210,21 +224,21 @@ class TestScoped < TestHBaseJRubyBase
210
224
  assert_equal new_versions, [versions[1]]
211
225
 
212
226
  # Deletes a column
213
- assert_equal 3, @table.get('row1').integer('cf2:c')
227
+ assert_equal 3, @table.get('row1').fixnum('cf2:c')
214
228
  @table.delete('row1', 'cf2:c')
215
229
  assert_nil @table.get('row1').to_hash['cf2:c']
216
230
 
217
231
  # Deletes a column with empty qualifier
218
- assert_equal 0, @table.get('row1').integer('cf1')
232
+ assert_equal 0, @table.get('row1').fixnum('cf1')
219
233
  @table.delete('row1', 'cf1:')
220
- assert_equal 1, @table.get('row1').integer('cf1:a')
221
- assert_equal 2, @table.get('row1').integer('cf1:b')
234
+ assert_equal 1, @table.get('row1').fixnum('cf1:a')
235
+ assert_equal 2, @table.get('row1').fixnum('cf1:b')
222
236
  assert_nil @table.get('row1').to_hash['cf1']
223
237
  assert_nil @table.get('row1').to_hash['cf1:']
224
238
 
225
239
  # Deletes a column family
226
- assert_equal 1, @table.get('row1').integer('cf1:a')
227
- assert_equal 2, @table.get('row1').integer('cf1:b')
240
+ assert_equal 1, @table.get('row1').fixnum('cf1:a')
241
+ assert_equal 2, @table.get('row1').fixnum('cf1:b')
228
242
  @table.delete('row1', 'cf1') # No trailing colon
229
243
  assert_nil @table.get('row1').to_hash['cf1:a']
230
244
  assert_nil @table.get('row1').to_hash['cf1:b']
@@ -240,7 +254,7 @@ class TestScoped < TestHBaseJRubyBase
240
254
  @table.delete ['row2'], ['row3', 'cf1:a']
241
255
  assert_nil @table.get('row2')
242
256
  assert_nil @table.get('row3').to_hash['cf1:a']
243
- assert_equal 2, @table.get('row3').integer('cf1:b')
257
+ assert_equal 2, @table.get('row3').fixnum('cf1:b')
244
258
  end
245
259
  end
246
260
 
@@ -8,14 +8,20 @@ class TestUtil < Test::Unit::TestCase
8
8
  Util = HBase::Util
9
9
 
10
10
  def test_bytea_conversion
11
- Util.import_java_classes!
12
-
13
11
  assert_raise(ArgumentError) { Util.to_bytes(10 ** 30) }
14
12
 
15
- [:fixnum, :int, :integer].each do |type|
13
+ [:fixnum, :long].each do |type|
16
14
  assert_equal 100, Util.from_bytes( type, Util.to_bytes(100) )
17
15
  assert_equal 100, Util.from_bytes( type, Util.to_bytes(HBase::ByteArray(100)) )
18
16
  end
17
+
18
+ assert_equal 100, Util.from_bytes( :byte, Util.to_bytes(:byte => 100) )
19
+ assert_equal 100, Util.from_bytes( :short, Util.to_bytes(:short => 100) )
20
+ assert_equal 100, Util.from_bytes( :int, Util.to_bytes(:int => 100) )
21
+ assert_raise(ArgumentError) { Util.to_bytes(:short => "Hello") }
22
+ assert_raise(ArgumentError) { Util.to_bytes(:xxx => 100) }
23
+ assert_raise(ArgumentError) { Util.to_bytes(:short => 100, :int => 200) }
24
+
19
25
  [:float, :double].each do |type|
20
26
  assert_equal 3.14, Util.from_bytes( type, Util.to_bytes(3.14) )
21
27
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: hbase-jruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.4
5
+ version: 0.1.5
6
6
  platform: java
7
7
  authors:
8
8
  - Junegunn Choi
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-30 00:00:00.000000000 Z
12
+ date: 2012-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit