hbase-jruby 0.1.4-java → 0.1.5-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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