[Groonga-commit] ranguba/groonga-client at 4fe1095 [master] Support TSV response format

アーカイブの一覧に戻る

Kouhei Sutou null+****@clear*****
Fri Jul 13 17:44:59 JST 2018


Kouhei Sutou	2018-07-13 17:44:59 +0900 (Fri, 13 Jul 2018)

  New Revision: 4fe10957e24d0fd89614d46b22b997635f3a31ec
  https://github.com/ranguba/groonga-client/commit/4fe10957e24d0fd89614d46b22b997635f3a31ec

  Message:
    Support TSV response format

  Added files:
    test/response/test-select-tsv.rb
  Modified files:
    lib/groonga/client/response/base.rb
    lib/groonga/client/response/select.rb
    test/response/helper.rb

  Modified: lib/groonga/client/response/base.rb (+44 -0)
===================================================================
--- lib/groonga/client/response/base.rb    2018-07-13 17:03:23 +0900 (d123778)
+++ lib/groonga/client/response/base.rb    2018-07-13 17:44:59 +0900 (41b74e8)
@@ -17,6 +17,7 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
+require "csv"
 require "rexml/document"
 require "json"
 
@@ -78,6 +79,9 @@ module Groonga
             when :xml
               header, body = parse_xml(raw_response)
               return_code = header[0] if header
+            when :tsv
+              header, body = parse_tsv(raw_response)
+              return_code = header["return_code"] if header
             else
               header = nil
               body = raw_response
@@ -129,6 +133,46 @@ module Groonga
               end
             end
           end
+
+          def parse_tsv(response)
+            tsv = CSV.new(response, col_sep: "\t")
+            raw_header = tsv.shift
+            return nil, nil if raw_header.nil?
+
+            header = parse_tsv_header(raw_header)
+            return header, nil unless header["return_code"].zero?
+
+            body = parse_tsv_body(tsv)
+            [header, body]
+          end
+
+          def parse_tsv_header(raw_header)
+            header = {
+              "return_code" => Integer(raw_header[0], 10),
+              "start_time" => Float(raw_header[1]),
+              "elapsed_time" => Float(raw_header[2]),
+            }
+            if raw_header.size >= 4
+              header["error"] = {
+                "message" => raw_header[3],
+              }
+              if raw_header.size >= 5
+                header["error"]["function"] = raw_header[4]
+                header["error"]["file"] = raw_header[5]
+                header["error"]["line"] = Integer(raw_header[6])
+              end
+            end
+            header
+          end
+
+          def parse_tsv_body(tsv)
+            body = []
+            tsv.each do |row|
+              break if row.size == 1 and row[0] == "END"
+              body << row
+            end
+            body
+          end
         end
 
         # @return [Groonga::Command] The command for the request.

  Modified: lib/groonga/client/response/select.rb (+72 -0)
===================================================================
--- lib/groonga/client/response/select.rb    2018-07-13 17:03:23 +0900 (72b8e07)
+++ lib/groonga/client/response/select.rb    2018-07-13 17:44:59 +0900 (aab9a42)
@@ -100,6 +100,78 @@ module Groonga
 
             drilldowns
           end
+
+          def parse_tsv_body(tsv)
+            record_sets = []
+
+            n_hits = parse_tsv_n_hits(tsv.shift)
+            columns = parse_tsv_columns(tsv.shift)
+            records = []
+            loop do
+              row = tsv.shift
+              break if row.size == 1 and row[0] == "END"
+              if (row.size % 4).zero? and row[0] == "[" and row[-1] == "]"
+                next_n_hits_row = records.pop
+                record_sets << [
+                  [n_hits],
+                  columns,
+                  *records,
+                ]
+                n_hits = parse_tsv_n_hits(next_n_hits_row)
+                columns = parse_tsv_columns(row)
+                records = []
+                next
+              end
+              records << parse_tsv_record(row)
+            end
+
+            record_sets << [
+              [n_hits],
+              columns,
+              *records,
+            ]
+            record_sets
+          end
+
+          def parse_tsv_n_hits(row)
+            Integer(row[0], 10)
+          end
+
+          def parse_tsv_columns(row)
+            columns = []
+            column = nil
+            row.each do |value|
+              case value
+              when "["
+                column = []
+              when "]"
+                columns << column
+              else
+                column << value
+              end
+            end
+            columns
+          end
+
+          def parse_tsv_record(row)
+            record = []
+            column_value = nil
+            row.each do |value|
+              case value
+              when "["
+                column_value = []
+              when "]"
+                record << column_value
+              else
+                if column_value
+                  column_value << value
+                else
+                  record << value
+                end
+              end
+            end
+            record
+          end
         end
 
         include Enumerable

  Modified: test/response/helper.rb (+5 -0)
===================================================================
--- test/response/helper.rb    2018-07-13 17:03:23 +0900 (4116433)
+++ test/response/helper.rb    2018-07-13 17:44:59 +0900 (11096d5)
@@ -30,4 +30,9 @@ module TestResponseHelper
     parse_raw_response_raw(command_name, {"output_type" => "xml"},
                            raw_response)
   end
+
+  def parse_raw_tsv_response(command_name, raw_response)
+    parse_raw_response_raw(command_name, {"output_type" => "tsv"},
+                           raw_response)
+  end
 end

  Added: test/response/test-select-tsv.rb (+127 -0) 100644
===================================================================
--- /dev/null
+++ test/response/test-select-tsv.rb    2018-07-13 17:44:59 +0900 (ab278f8)
@@ -0,0 +1,127 @@
+# Copyright (C) 2018  Kouhei Sutou <kou �� clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+require "response/helper"
+
+class TestResponseSelectTSV < Test::Unit::TestCase
+  include TestResponseHelper
+
+  def drilldown(key, n_hits, records)
+    Groonga::Client::Response::Select::Drilldown.new(key, n_hits, records)
+  end
+
+  def test_error
+    raw_response = <<-TSV
+-22	0	0.0	"message"	"function"	"file"	29
+
+END
+    TSV
+
+    response = parse_raw_tsv_response("select", raw_response)
+    assert_equal({
+                   :return_code => -22,
+                   :start_time => Time.at(0),
+                   :elapsed_time => 0.0,
+                   :error => {
+                     :message => "message",
+                     :function => "function",
+                     :file => "file",
+                     :line => 29,
+                   },
+                 },
+                 {
+                   :return_code => response.return_code,
+                   :start_time => response.start_time,
+                   :elapsed_time => response.elapsed_time,
+                   :error => {
+                     :message => response.message,
+                     :function => response.function,
+                     :file => response.file,
+                     :line => response.line,
+                   },
+                 })
+  end
+
+  def test_basic
+    raw_response = <<-TSV
+ 0	0	0.0
+100
+[	"_id"	"UInt32"	]
+1
+2
+END
+    TSV
+
+    response = parse_raw_tsv_response("select", raw_response)
+    assert_equal({
+                   :return_code => 0,
+                   :start_time => Time.at(0),
+                   :elapsed_time => 0.0,
+                   :records => [
+                     {"_id" => "1"},
+                     {"_id" => "2"},
+                   ],
+                 },
+                 {
+                   :return_code => response.return_code,
+                   :start_time => response.start_time,
+                   :elapsed_time => response.elapsed_time,
+                   :records => response.records,
+                 })
+  end
+
+  def test_drilldown
+    raw_response = <<-TSV
+ 0	0	0.0
+100
+[	"_id"	"UInt32"	]
+7
+[	"_key"	"ShortText"	]	[	"_nsubrecs"	"UInt32"	]
+"2.2.0"	"18044"
+"2.3.0"	"18115"
+"2.4.0"	"14594"
+END
+    TSV
+
+    response = parse_raw_response_raw("select",
+                                      {
+                                        "drilldown" => "version",
+                                        "output_type" => "tsv",
+                                      },
+                                      raw_response)
+    drilldown_records = [
+      {"_key" => "2.2.0", "_nsubrecs" => "18044"},
+      {"_key" => "2.3.0", "_nsubrecs" => "18115"},
+      {"_key" => "2.4.0", "_nsubrecs" => "14594"},
+    ]
+    assert_equal({
+                   :return_code => 0,
+                   :start_time => Time.at(0),
+                   :elapsed_time => 0.0,
+                   :records => [],
+                   :drilldowns => [
+                     drilldown("version", 7, drilldown_records),
+                   ],
+                 },
+                 {
+                   :return_code => response.return_code,
+                   :start_time => response.start_time,
+                   :elapsed_time => response.elapsed_time,
+                   :records => response.records,
+                   :drilldowns => response.drilldowns,
+                 })
+  end
+end
-------------- next part --------------
HTML����������������������������...
URL: https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20180713/fa6c9099/attachment-0001.htm 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る