diff --git src/main/ruby/hbase/hbase.rb src/main/ruby/hbase/hbase.rb index 2c37840..fa1c3ec 100644 --- src/main/ruby/hbase/hbase.rb +++ src/main/ruby/hbase/hbase.rb @@ -45,8 +45,8 @@ module Hbase end # Create new one each time - def table(table, formatter) - ::Hbase::Table.new(configuration, table, formatter) + def table(table, formatter, shell) + ::Hbase::Table.new(configuration, table, formatter, shell) end def replication_admin(formatter) diff --git src/main/ruby/hbase/table.rb src/main/ruby/hbase/table.rb index 6dcf47e..8cfdb89 100644 --- src/main/ruby/hbase/table.rb +++ src/main/ruby/hbase/table.rb @@ -26,8 +26,10 @@ module Hbase class Table include HBaseConstants - def initialize(configuration, table_name, formatter) + def initialize(configuration, table_name, formatter, shell) @table = org.apache.hadoop.hbase.client.HTable.new(configuration, table_name) + #create scan command, so we get the right formatting + @shell = shell end #---------------------------------------------------------------------------------------------- @@ -204,8 +206,9 @@ module Hbase end #---------------------------------------------------------------------------------------------- - # Scans whole table or a range of keys and returns rows matching specific criterias - def scan(args = {}) + # Scans whole table or a range of keys and returns rows matching specific criteria + + def scan_internal(args = {}) unless args.kind_of?(Hash) raise ArgumentError, "Arguments should be a hash. Failed to parse #{args.inspect}, #{args.class}" end @@ -345,5 +348,44 @@ module Hbase (maxlength != -1) ? val[0, maxlength] : val end + #---------------------------- + def help + return <<-EOF + Access an HTable. The table is accessed based on the name of the table + and the current default configuration (hbase-site.xml and hbase-default.xml). + + There are a variety of things you can do with a table. For instance, say + you have a table 't': + + hbase> t.scan + + Will get you all the rows in t. + + Similarly, to put a row into table t, assuming it was created with + the column family 'fam': + + hbase> t.put 'row', 'fam', 'value' + + Other commands include things like: get, delete, deleteall, is_meta_table?, + get_all_columns, get_counter, count, incr. These functions, along with + the standard JRuby object methods are also available via tab completion. + + For more information on how to use each of these commands, you can also just + type that command into the terminal, as such: + + hbase> scan + + which will output a helpful help message. Note that when using these commands, + you do NOT need start with the table name in that command as the command is + already tied to the table implementation. For example, the following are + equivalent: + + hbase> scan 't' + + and + + hbase> t.scan + EOF + end end end diff --git src/main/ruby/shell.rb src/main/ruby/shell.rb index 53f3de8..c8c720c 100644 --- src/main/ruby/shell.rb +++ src/main/ruby/shell.rb @@ -80,7 +80,7 @@ module Shell end def hbase_table(name) - hbase.table(name, formatter) + hbase.table(name, formatter, self) end def hbase_replication_admin @@ -93,10 +93,15 @@ module Shell def export_commands(where) ::Shell.commands.keys.each do |cmd| + # here where is the IRB namespace + # this method just adds the call to the specified command + # which just references back to 'this' shell object + # a decently extensible way to add commands where.send :instance_eval, <<-EOF def #{cmd}(*args) - @shell.command('#{cmd}', *args) + ret = @shell.command('#{cmd}', *args) puts + return ret end EOF end @@ -211,6 +216,7 @@ Shell.load_command_group( :commands => %w[ status version + get_table ] ) diff --git src/main/ruby/shell/commands.rb src/main/ruby/shell/commands.rb index af6df33..4a64f3e 100644 --- src/main/ruby/shell/commands.rb +++ src/main/ruby/shell/commands.rb @@ -37,8 +37,6 @@ module Shell puts "Here is some help for this command:" puts help puts - ensure - return nil end def admin @@ -69,7 +67,15 @@ module Shell formatter.header formatter.footer(now) end - + + def format_and_return_simple_command + now = Time.now + ret = yield + formatter.header + formatter.footer(now) + return ret + end + def translate_hbase_exceptions(*args) yield rescue org.apache.hadoop.hbase.TableNotFoundException diff --git src/main/ruby/shell/commands/create.rb src/main/ruby/shell/commands/create.rb index 14c1b0f..92270ae 100644 --- src/main/ruby/shell/commands/create.rb +++ src/main/ruby/shell/commands/create.rb @@ -38,13 +38,22 @@ Examples: hbase> # Optionally pre-split the table into NUMREGIONS, using hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname) hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'} + + You can also keep around a reference to the created table: + + hbase> t1 = create 't1', 'f1' + + Which gives you a reference to the table named 't1', on which you can then + call methods. EOF end def command(table, *args) format_simple_command do - admin.create(table, *args) + ret = admin.create(table, *args) end + #and then return the table you just created + table(table) end end end diff --git src/main/ruby/shell/commands/get_table.rb src/main/ruby/shell/commands/get_table.rb new file mode 100644 index 0000000..e34b0a0 --- /dev/null +++ src/main/ruby/shell/commands/get_table.rb @@ -0,0 +1,28 @@ +module Shell + module Commands + class GetTable < Command + def help + return <<-EOF +Get the given table name and return it as an actual object to +be manipulated by the user. See table.help for more information +on how to use the table. +Eg. + + hbase> t1 = get_table 't1' + +returns the table named 't1' as a table object. You can then do + + hbase> t1.help + +which will then print the help for that table. +EOF + end + + def command(table, *args) + format_and_return_simple_command do + table(table) + end + end + end + end +end diff --git src/main/ruby/shell/commands/scan.rb src/main/ruby/shell/commands/scan.rb index e58aaac..5e9f5f7 100644 --- src/main/ruby/shell/commands/scan.rb +++ src/main/ruby/shell/commands/scan.rb @@ -62,10 +62,15 @@ EOF end def command(table, args = {}) + scan(table(table), args) + end + + def scan(table, args = {}) now = Time.now formatter.header(["ROW", "COLUMN+CELL"]) - count = table(table).scan(args) do |row, cells| + #actually do the scanning + count = table.scan_internal(args) do |row, cells| formatter.row([ row, cells ]) end @@ -74,3 +79,15 @@ EOF end end end + +#extension of the table class s.t. it will call the scan object +module Hbase + class Table + + #add the ability to scan a table using the correct scan object + def scan(args = {}) + @scan ||= ::Shell::Commands::Scan.new(@shell) + @scan.scan(self, args) + end + end +end diff --git src/test/ruby/hbase/admin_test.rb src/test/ruby/hbase/admin_test.rb index 0c2672b..278090b 100644 --- src/test/ruby/hbase/admin_test.rb +++ src/test/ruby/hbase/admin_test.rb @@ -310,5 +310,13 @@ module Hbase assert_no_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name)) assert_no_match(eval("/" + key2 + "/"), admin.describe(@test_name)) end + + define_test "get_table should get a real table" do + drop_test_table(@test_name) + create_test_table(@test_name) + + table = table(@test_name) + assert_not_equal(nil, table) + end end end diff --git src/test/ruby/hbase/table_test.rb src/test/ruby/hbase/table_test.rb index 5d56e18..d455470 100644 --- src/test/ruby/hbase/table_test.rb +++ src/test/ruby/hbase/table_test.rb @@ -123,7 +123,7 @@ module Hbase define_test "put should work with integer values" do @test_table.put("123", "x:a", 4) end - + #------------------------------------------------------------------------------- define_test "delete should work without timestamp" do