Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 075467501a
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 181 lines (163 sloc) 7.733 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
module Stargate
  module Operation
    module RowOperation

      CONVERTER = { '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', "'" => '&apos;', '"' => '&quot;' }.freeze

      # Add a row to HBase
      #
      # Example:
      # client = Stargate::Client.new("http://localhost:8080")
      # client.set("test-hbase-stargate", "row1", {"col1:cell1" => "value for column 1, cell 1", "col1:cell2" => "value 2"})
      #
      # @param [String] table_name The HBase table name
      # @param [String] row The row id
      # @param [Hash] columns hash consisting of the keys as column names and their corresponding values
      # @param [Integer] timestamp optional timestamp argument. Can be any custom value, but HBase uses the millisecond time since epoch.
      # @return [true,false] true or false depending on whether the row was added successfully
      def set(table_name, row, columns, timestamp = nil)
        cells = []
        columns.each do |name, value|
          escaped_name = name.gsub(/[&<>'"]/) { |match| CONVERTER[match] }
          cell = {}
          cell["@column"] = Base64.encode64(escaped_name) rescue ''
          cell["@timestamp"] = timestamp unless timestamp.nil?
          cell["$"] = Base64.encode64(value) rescue ''
          cells << cell
        end

        request = Request::RowRequest.new(table_name, row, timestamp)
        json_data = Yajl::Encoder.encode({"Row" => {"@key" => Base64.encode64(row), "Cell" => cells}})

        handle_exception(table_name, row) do
          response = rest_post_response(request.create(columns.keys), json_data, {'Content-Type' => 'application/json'})
          Response::RowResponse.new(response, :create_row).parse
        end
      end

      def multi_get(table_name, rows, options = {})
        if rows.is_a? String
          request = Request::RowRequest.new(table_name, rows, options.delete(:timestamp))
        elsif rows.is_a? Array

        end
        options[:version] ||= 1

        handle_exception(table_name, rows) do
          rows = {}
          Response::RowResponse.new(rest_get(request.show(options.delete(:columns), options)), :show_row).parse.each do |row|
            row.table_name = table_name
            rows[row.name] = row
          end
          return rows
        end
      end

      # Get a row from HBase
      #
      # Example:
      # client = Stargate::Client.new("http://localhost:8080")
      # client.get("test-hbase-stargate", "row1", :timestamp => 1321846232, :columns => ["col1:cell1"], :version => 3)
      #
      # @param [String] table_name The HBase table name
      # @param [String] row The row id
      # @param [Hash] options the options to retrieve the row with
      # @option options [Integer] :timestamp A specific timestamp the rows should have (in seconds)
      # @option options [Array<String>] :columns List of columns to get
      # @option options [Integer] :versions The number of versions to get back
      # @return [Model::Row] object corresponding to the requested row, or nil if it could not be found
      def get(table_name, row, options = {})
        multi_get(table_name, row, options)[row]
      end

      # Get a row from HBase
      #
      # Example:
      # client = Stargate::Client.new("http://localhost:8080")
      # row = client.show_row("test-hbase-stargate", "row1", nil, nil, :version => 2)
      #
      # @deprecated Use the {#get} method instead
      # @param [String] table_name The HBase table name
      # @param [String] name The row id
      # @param [Integer] timestamp optional timestamp
      # @param [Array<String>] columns name of the columns to retrieve. Use nil to get them all.
      # @param [Hash] options the options to retrieve the row with
      # @option options [Integer] :versions The number of versions to get back
      # @return [Model::Row] object corresponding to the requested row, or nil if it could not be found
      def show_row(table_name, name, timestamp = nil, columns = nil, options = {})
        handle_exception(table_name, name) do
          options[:version] ||= 1

          request = Request::RowRequest.new(table_name, name, timestamp)
          rows = Response::RowResponse.new(rest_get(request.show(columns, options)), :show_row).parse
          if rows.size == 1
            row = rows.first
            row.table_name = table_name
            row
          else
            rows.each do |row|
              row.table_name = table_name
            end
            rows
          end
        end
      end

      # Add a row to HBase
      #
      # Example:
      # client = Stargate::Client.new("http://localhost:8080")
      # client.create_row("test-hbase-stargate", "row1", nil, [{ :name => "col1:cell1", :value => "row2-col1-cell1" }, { :name => "col1:cell2", :value => "row2-col1-cell2" }])
      #
      # @deprecated Use the {#set} method instead
      # @param [String] table_name The HBase table name
      # @param [String] name The row id
      # @param [Integer] timestamp optional timestamp argument. Can be any custom value (in seconds), but HBase uses the millisecond time since epoch.
      # @param [Hash, Array<Hash>] columns
      # @return [true,false] true or false depending on whether the row was added successfully
      def create_row(table_name, name, timestamp = nil, columns = nil)
        handle_exception(table_name, name) do
          request = Request::RowRequest.new(table_name, name, timestamp)
          data = []
          if columns
            if columns.instance_of? Array
              data = columns
            elsif columns.instance_of? Hash
              data = [columns]
            else
              raise ArgumentError, "Column data should be given as an Array or Hash"
            end
          end

          xml_data = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><CellSet>"
          xml_data << "<Row key='#{Base64.encode64(name) rescue ''}'>"
          data.each do |d|
            escape_name = d[:name].gsub(/[&<>'"]/) { |match| CONVERTER[match] }
            xml_data << "<Cell "
            xml_data << "timestamp='#{timestamp}' " if timestamp
            xml_data << "column='#{Base64.encode64(escape_name) rescue ''}'>"
            xml_data << "#{Base64.encode64(d[:value]) rescue ''}"
            xml_data << "</Cell>"
          end
          xml_data << "</Row></CellSet>"

          Response::RowResponse.new(rest_post_response(request.create(data.map{|col| col[:name]}), xml_data), :create_row).parse
        end
      end

      # Delete a row in HBase
      #
      # @param [String] table_name The HBase table name
      # @param [String] name The row id
      # @param [Integer] timestamp optional timestamp value (deletes all timestamp if not specified)
      # @param [Array<String>] optional list of specific columns to delete (deletes all columns if not specified)
      def delete_row(table_name, name, timestamp = nil, columns = nil)
        handle_exception(table_name, name) do
          request = Request::RowRequest.new(table_name, name, timestamp)
          response = rest_delete_response(request.delete(columns))
          Response::RowResponse.new(response, :delete_row).parse
        end
      end

      private

        def handle_exception(table_name, row = nil)
          begin
            yield
          rescue => e
            if e.to_s.include?("Table")
              raise TableNotFoundError, "Table '#{table_name}' not found"
            elsif !row.nil? && e.to_s.include?("404 Not Found")
              raise RowNotFoundError, "Row '#{row}' not found"
            else
              raise StandardError, "Following error encountered: #{e.message}"
            end
          end
        end

    end
  end
end
Something went wrong with that request. Please try again.