diff --git hbase-shell/src/main/ruby/hbase.rb hbase-shell/src/main/ruby/hbase.rb index 87512bf..75c5d5e 100644 --- hbase-shell/src/main/ruby/hbase.rb +++ hbase-shell/src/main/ruby/hbase.rb @@ -57,6 +57,7 @@ module HBaseConstants SPLITALGO = 'SPLITALGO' NUMREGIONS = 'NUMREGIONS' CONFIGURATION = org.apache.hadoop.hbase.HConstants::CONFIGURATION + ATTRIBUTES="ATTRIBUTES" # Load constants from hbase java API def self.promote_constants(constants) diff --git hbase-shell/src/main/ruby/hbase/table.rb hbase-shell/src/main/ruby/hbase/table.rb index 13d7646..571a965 100644 --- hbase-shell/src/main/ruby/hbase/table.rb +++ hbase-shell/src/main/ruby/hbase/table.rb @@ -127,9 +127,14 @@ EOF # they will be much less likely to tab complete to the 'dangerous' internal method #---------------------------------------------------------------------------------------------- # Put a cell 'value' at specified table/row/column - def _put_internal(row, column, value, timestamp = nil) + def _put_internal(row, column, value, args = {}) p = org.apache.hadoop.hbase.client.Put.new(row.to_s.to_java_bytes) family, qualifier = parse_column_name(column) + if args.any? + attributes = args[ATTRIBUTES] + timestamp = args[TIMESTAMP] + set_attributes(p, attributes) if attributes + end if timestamp p.add(family, qualifier, timestamp, value.to_s.to_java_bytes) else @@ -219,7 +224,7 @@ EOF # Get maxlength parameter if passed maxlength = args.delete(MAXLENGTH) if args[MAXLENGTH] filter = args.delete(FILTER) if args[FILTER] - + attributes = args[ATTRIBUTES] unless args.empty? columns = args[COLUMN] || args[COLUMNS] if args[VERSIONS] @@ -251,9 +256,13 @@ EOF get.setTimeStamp(args[TIMESTAMP]) if args[TIMESTAMP] get.setTimeRange(args[TIMERANGE][0], args[TIMERANGE][1]) if args[TIMERANGE] else - # May have passed TIMESTAMP and row only; wants all columns from ts. - unless ts = args[TIMESTAMP] || tr = args[TIMERANGE] - raise ArgumentError, "Failed parse of #{args.inspect}, #{args.class}" + if attributes + set_attributes(get, attributes) if attributes + else + # May have passed TIMESTAMP and row only; wants all columns from ts. + unless ts = args[TIMESTAMP] || tr = args[TIMERANGE] + raise ArgumentError, "Failed parse of #{args.inspect}, #{args.class}" + end end get.setMaxVersions(vers) @@ -261,6 +270,7 @@ EOF get.setTimeStamp(ts.to_i) if args[TIMESTAMP] get.setTimeRange(args[TIMERANGE][0], args[TIMERANGE][1]) if args[TIMERANGE] end + set_attributes(get, attributes) if attributes end unless filter.class == String @@ -333,6 +343,7 @@ EOF versions = args["VERSIONS"] || 1 timerange = args[TIMERANGE] raw = args["RAW"] || false + attributes = args[ATTRIBUTES] # Normalize column names columns = [columns] if columns.class == String @@ -367,6 +378,7 @@ EOF scan.setMaxVersions(versions) if versions > 1 scan.setTimeRange(timerange[0], timerange[1]) if timerange scan.setRaw(raw) + set_attributes(scan, attributes) if attributes else scan = org.apache.hadoop.hbase.client.Scan.new end @@ -408,6 +420,15 @@ EOF return ((block_given?) ? count : res) end + # Apply OperationAttributes to puts/scans/gets + def set_attributes(oprattr, attributes) + raise(ArgumentError, "#{"ATTRIBUTES"} must be a Hash type") unless attributes.kind_of?(Hash) + for k,v in attributes + v = v.to_s unless v.nil? + oprattr.setAttribute(k.to_s, v.to_java_bytes) + end + end + #---------------------------- # Add general administration utilities to the shell # each of the names below adds this method name to the table diff --git hbase-shell/src/main/ruby/shell/commands/get.rb hbase-shell/src/main/ruby/shell/commands/get.rb index 4344d68..7ac4033 100644 --- hbase-shell/src/main/ruby/shell/commands/get.rb +++ hbase-shell/src/main/ruby/shell/commands/get.rb @@ -36,6 +36,7 @@ a dictionary of column(s), timestamp, timerange and versions. Examples: hbase> get 't1', 'r1', 'c1' hbase> get 't1', 'r1', 'c1', 'c2' hbase> get 't1', 'r1', ['c1', 'c2'] + hbsase> get 't1','r1', {COLUMN => 'c1', ATTRIBUTES => {'mykey'=>'myvalue'}} Besides the default 'toStringBinary' format, 'get' also supports custom formatting by column. A user can define a FORMATTER by adding it to the column name in the get diff --git hbase-shell/src/main/ruby/shell/commands/put.rb hbase-shell/src/main/ruby/shell/commands/put.rb index 17e7a5f..e729e77 100644 --- hbase-shell/src/main/ruby/shell/commands/put.rb +++ hbase-shell/src/main/ruby/shell/commands/put.rb @@ -26,22 +26,22 @@ Put a cell 'value' at specified table/row/column and optionally timestamp coordinates. To put a cell value into table 't1' at row 'r1' under column 'c1' marked with the time 'ts1', do: - hbase> put 't1', 'r1', 'c1', 'value', ts1 + hbase> put 't1', 'r1', 'c1', 'value', {TIMESTAMP=>100, ATTRIBUTES=>{'mykey'=>'myvalue'}} The same commands also can be run on a table reference. Suppose you had a reference t to table 't1', the corresponding command would be: - hbase> t.put 'r1', 'c1', 'value', ts1 + hbase> t.put 'r1', 'c1', 'value', ts1, {TIMESTAMP=>100, ATTRIBUTES=>{'mykey'=>'myvalue'}} EOF end - def command(table, row, column, value, timestamp = nil) - put table(table), row, column, value, timestamp + def command(table, row, column, value, args = {}) + put table(table), row, column, value, args end - def put(table, row, column, value, timestamp = nil) + def put(table, row, column, value, args = {}) format_simple_command do - table._put_internal(row, column, value, timestamp) + table._put_internal(row, column, value, args) end end end diff --git hbase-shell/src/main/ruby/shell/commands/scan.rb hbase-shell/src/main/ruby/shell/commands/scan.rb index 364fd6e..0564ad8 100644 --- hbase-shell/src/main/ruby/shell/commands/scan.rb +++ hbase-shell/src/main/ruby/shell/commands/scan.rb @@ -46,7 +46,8 @@ Some examples: (QualifierFilter (>=, 'binary:xyz'))) AND (TimestampsFilter ( 123, 456))"} hbase> scan 't1', {FILTER => org.apache.hadoop.hbase.filter.ColumnPaginationFilter.new(1, 0)} - +For setting the Operation Attributes + hbase> scan 't1', { COLUMNS => ['c1', 'c2'], ATTRIBUTES => {'mykey' => 'myvalue'}} For experts, there is an additional option -- CACHE_BLOCKS -- which switches block caching for the scanner on (true) or off (false). By default it is enabled. Examples: diff --git hbase-shell/src/test/ruby/hbase/table_test.rb hbase-shell/src/test/ruby/hbase/table_test.rb index 4eba3e2..ffcf47d 100644 --- hbase-shell/src/test/ruby/hbase/table_test.rb +++ hbase-shell/src/test/ruby/hbase/table_test.rb @@ -104,10 +104,11 @@ module Hbase # Insert data to perform delete operations @test_table.put("101", "x:a", "1") - @test_table.put("101", "x:a", "2", Time.now.to_i) + @test_ts=Time.now.to_i + #@test_table.put("101", "x:a", "2", {TIMESTAMP=>@test_ts}) - @test_table.put("102", "x:a", "1",1212) - @test_table.put("102", "x:a", "2", 1213) + @test_table.put("102", "x:a", "1",{TIMESTAMP=>1212}) + @test_table.put("102", "x:a", "2", {TIMESTAMP=>1213}) @test_table.put(103, "x:a", "3") @test_table.put(103, "x:a", "4") @@ -124,7 +125,8 @@ module Hbase end define_test "put should work with timestamp" do - @test_table.put("123", "x:a", "2", Time.now.to_i) + @test_ts=Time.now.to_i + @test_table.put("123", "x:a", "2", {TIMESTAMP=>@test_ts}) end define_test "put should work with integer keys" do @@ -134,7 +136,10 @@ module Hbase define_test "put should work with integer values" do @test_table.put("123", "x:a", 4) end - + + define_test "put should work with attributes" do + @test_table.put("123", "x:a", 4, {ATTRIBUTES=>{'mykey'=>'myvalue'}}) + end #------------------------------------------------------------------------------- define_test "delete should work without timestamp" do @@ -209,10 +214,10 @@ module Hbase # Instert test data @test_ts = 12345678 @test_table.put(1, "x:a", 1) - @test_table.put(1, "x:b", 2, @test_ts) + @test_table.put(1, "x:b", 2, {TIMESTAMP=>@test_ts}) @test_table.put(2, "x:a", 11) - @test_table.put(2, "x:b", 12, @test_ts) + @test_table.put(2, "x:b", 12, {TIMESTAMP=>@test_ts}) end define_test "count should work w/o a block passed" do @@ -441,7 +446,7 @@ module Hbase assert_not_nil(res['2']['x:a']) assert_not_nil(res['2']['x:b']) end - + define_test "scan should support COLUMNS parameter with a single column name" do res = @test_table._scan_internal COLUMNS => 'x:a' assert_not_nil(res)