groonga-client 0.6.0 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eaec3aab0752df6b5832fe16cb3c79d107103636b06a603ecb2e453bd6e29bec
4
- data.tar.gz: cc03ea25d9b87599a6fc10cc553716c3bd7e0b885b2887f7a414b0377490e37d
3
+ metadata.gz: 0c6eb335d9ea4011c1e5b3681dfd8e9252796b95d24c802df1a769757821b8bf
4
+ data.tar.gz: 19824fe10455c126d229c1af171a8483ee67b15df08df78a9b8ec43dc0e661cd
5
5
  SHA512:
6
- metadata.gz: 16a4c67ddfa8bb7f401ff0cd5f49d852f3f279966c3839379ae0ed0f29629b8402ae7b14a87087f263440b8ee0365eb646688a8a3ad7b1cc9979d9ddd3bc61d1
7
- data.tar.gz: 86c7edc062f853a4d56e18b0b43477f6317630471de314d4952ab8dd7b9a85146180ce8d5e93ce7f687e0345ec6a26f938846409b3ad3bdcd45677ec4e0029f2
6
+ metadata.gz: b48b94c52345192fbb20ffbde0d450cd819ca97097b4b0a549ed285645f7a85278392ce51abefb29b055c8505aca5574789e0312fc81b6a7615eeed261e57933
7
+ data.tar.gz: 2d58742abe16488dbcfcde075d9102b3988f27b58e8c398a60ba75406d0b17e11ac2ebf8d708c7ebe1b9e7b1a13adad0a59fdabaf646cd376c3463925f7f9f5c
data/doc/text/news.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # NEWS
2
2
 
3
+ ## 0.6.5 - 2021-03-15
4
+
5
+ ### Fixes
6
+
7
+ * `Groonga::Client::Request::Select::LabeledDrilldown#keys`: Fixed a
8
+ bug that this uses wrong parameter name.
9
+
10
+ ## 0.6.4 - 2021-02-24
11
+
12
+ ### Improvements
13
+
14
+ * Added support for Ruby 3.0.
15
+
16
+ ## 0.6.3 - 2020-06-08
17
+
18
+ ### Improvements
19
+
20
+ * `groonga-client`:
21
+
22
+ * Added support for `-load-input-type=apache-arrow`.
23
+
24
+ * Added `--load-lock-table`.
25
+
26
+ * `http`: Added support for debugging by
27
+ `GROONGA_CLIENT_HTTP_DEBUG=yes` environment variable.
28
+
29
+ * Added support for response in Apache Arrow.
30
+
31
+ ## 0.6.2 - 2019-09-02
32
+
33
+ ### Improvements
34
+
35
+ * `Groonga::Client::Response::LogicalSelect`: Added.
36
+
37
+ * `Groonga::Client::Response::Select#raw_columns`: Added.
38
+
39
+ * `Groonga::Client::Response::Select#raw_records`: Added.
40
+
41
+ * `Groonga::Client::Response::LogicalRangeFilter`: Added.
42
+
43
+ ## 0.6.1 - 2019-07-27
44
+
45
+ ### Improvements
46
+
47
+ * `Groonga::Client::Request::Select`: Added support for drilldowns
48
+ in slice.
49
+
3
50
  ## 0.6.0 - 2018-08-30
4
51
 
5
52
  ### Improvements
@@ -1,7 +1,7 @@
1
1
  # -*- mode: ruby -*-
2
2
  #
3
3
  # Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
4
- # Copyright (C) 2014-2016 Kouhei Sutou <kou@clear-code.com>
4
+ # Copyright (C) 2014-2021 Sutou Kouhei <kou@clear-code.com>
5
5
  #
6
6
  # This library is free software; you can redistribute it and/or
7
7
  # modify it under the terms of the GNU Lesser General Public
@@ -48,9 +48,10 @@ Gem::Specification.new do |spec|
48
48
  end
49
49
 
50
50
  spec.add_runtime_dependency("gqtp", ">= 1.0.4")
51
- spec.add_runtime_dependency("groonga-command", ">= 1.2.8")
51
+ spec.add_runtime_dependency("groonga-command", ">= 1.4.7")
52
52
  spec.add_runtime_dependency("groonga-command-parser", ">= 1.1.0")
53
53
  spec.add_runtime_dependency("hashie")
54
+ spec.add_runtime_dependency("rexml")
54
55
 
55
56
  spec.add_development_dependency("bundler")
56
57
  spec.add_development_dependency("rake")
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2018 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2015-2020 Sutou Kouhei <kou@clear-code.com>
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,11 @@ require "json"
19
19
  require "pathname"
20
20
  require "securerandom"
21
21
 
22
+ begin
23
+ require "arrow"
24
+ rescue LoadError
25
+ end
26
+
22
27
  require "groonga/command/parser"
23
28
 
24
29
  require "groonga/client"
@@ -30,6 +35,12 @@ module Groonga
30
35
  class GroongaClient
31
36
  def initialize
32
37
  @chunk = false
38
+ @load_input_type = "json"
39
+ @available_load_input_types = ["json"]
40
+ if Object.const_defined?(:Arrow)
41
+ @available_load_input_types << "apache-arrow"
42
+ end
43
+ @load_lock_table = false
33
44
 
34
45
  @runner_options = {
35
46
  :split_load_chunk_size => 10000,
@@ -46,7 +57,9 @@ module Groonga
46
57
  parse_command_line(option_parser)
47
58
  end
48
59
 
49
- parser.open_client(:chunk => @chunk) do |client|
60
+ parser.open_client(:chunk => @chunk,
61
+ :load_input_type => @load_input_type,
62
+ :load_lock_table => @load_lock_table) do |client|
50
63
  runner = Runner.new(client, @runner_options)
51
64
 
52
65
  if command_file_paths.empty?
@@ -99,6 +112,20 @@ module Groonga
99
112
  @runner_options[:split_load_chunk_size] = size
100
113
  end
101
114
 
115
+ parser.on("--load-input-type=TYPE",
116
+ @available_load_input_types,
117
+ "Use TYPE as input type for load.",
118
+ "[#{@available_load_input_types.join(", ")}]",
119
+ "(#{@load_input_types})") do |type|
120
+ @load_input_type = type
121
+ end
122
+
123
+ parser.on("--[no-]load-lock-table",
124
+ "Use lock_table=yes for load.",
125
+ "(#{@load_lock_table})") do |boolean|
126
+ @load_lock_table = boolean
127
+ end
128
+
102
129
  parser.on("--[no-]generate-request-id",
103
130
  "Add auto generated request ID to all commands.",
104
131
  "(#{@runner_options[:generate_request_id]})") do |boolean|
@@ -1,5 +1,5 @@
1
1
  # Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
2
- # Copyright (C) 2013-2016 Kouhei Sutou <kou@clear-code.com>
2
+ # Copyright (C) 2013-2020 Sutou Kouhei <kou@clear-code.com>
3
3
  #
4
4
  # This library is free software; you can redistribute it and/or
5
5
  # modify it under the terms of the GNU Lesser General Public
@@ -55,9 +55,15 @@ module Groonga
55
55
  @options = options
56
56
  end
57
57
 
58
+ DEBUG = (ENV["GROONGA_CLIENT_HTTP_DEBUG"] == "yes")
58
59
  def send(command)
59
60
  begin
60
- HTTPClient.start(@url.host, @url.port, start_options) do |http|
61
+ http = HTTPClient.new(@url.host, @url.port)
62
+ http.set_debug_output($stderr) if DEBUG
63
+ start_options.each do |key, value|
64
+ http.__send__("#{key}=", value)
65
+ end
66
+ http.start do
61
67
  http.read_timeout = read_timeout
62
68
  response = send_request(http, command)
63
69
  case response
@@ -141,18 +147,7 @@ module Groonga
141
147
 
142
148
  def send_request(http, command)
143
149
  if command.is_a?(Groonga::Command::Load)
144
- raw_values = command[:values]
145
- command[:values] = nil
146
- path = resolve_path(@url, command.to_uri_format)
147
- command[:values] = raw_values
148
- request = Net::HTTP::Post.new(path, headers)
149
- request.content_type = "application/json"
150
- if @options[:chunk]
151
- request["Transfer-Encoding"] = "chunked"
152
- else
153
- request.content_length = raw_values.bytesize
154
- end
155
- request.body_stream = StringIO.new(raw_values)
150
+ request = prepare_load_request(command)
156
151
  else
157
152
  path = resolve_path(@url, command.to_uri_format)
158
153
  request = Net::HTTP::Get.new(path, headers)
@@ -167,6 +162,42 @@ module Groonga
167
162
  }
168
163
  end
169
164
 
165
+ def prepare_load_request(command)
166
+ path_prefix = command.path_prefix
167
+ command = command.class.new(command.command_name,
168
+ command.arguments,
169
+ [])
170
+ command.path_prefix = path_prefix
171
+ case @options[:load_input_type]
172
+ when "apache-arrow"
173
+ command[:input_type] = "apache-arrow"
174
+ content_type = "application/x-apache-arrow-streaming"
175
+ arrow_table = command.build_arrow_table
176
+ if arrow_table
177
+ buffer = Arrow::ResizableBuffer.new(1024)
178
+ arrow_table.save(buffer, format: :stream)
179
+ body = buffer.data.to_s
180
+ else
181
+ body = ""
182
+ end
183
+ command.arguments.delete(:values)
184
+ else
185
+ content_type = "application/json"
186
+ body = command.arguments.delete(:values)
187
+ end
188
+ command[:lock_table] = "yes" if @options[:load_lock_table]
189
+ path = resolve_path(@url, command.to_uri_format)
190
+ request = Net::HTTP::Post.new(path, headers)
191
+ if @options[:chunk]
192
+ request["Transfer-Encoding"] = "chunked"
193
+ else
194
+ request.content_length = body.bytesize
195
+ end
196
+ request.content_type = content_type
197
+ request.body_stream = StringIO.new(body)
198
+ request
199
+ end
200
+
170
201
  def setup_authentication(request)
171
202
  userinfo = @url.userinfo
172
203
  return if userinfo.nil?
@@ -595,7 +595,7 @@ module Groonga
595
595
  end
596
596
 
597
597
  def keys(values)
598
- @request.values_parameter([:"#{prefix}keys"], values)
598
+ @request.values_parameter(:"#{prefix}keys", values)
599
599
  end
600
600
 
601
601
  def sort_keys(value)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2016 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2014-2019 Sutou Kouhei <kou@clear-code.com>
2
2
  # Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
3
3
  #
4
4
  # This library is free software; you can redistribute it and/or
@@ -30,6 +30,8 @@ require "groonga/client/response/lock-clear"
30
30
  require "groonga/client/response/log-level"
31
31
  require "groonga/client/response/log-put"
32
32
  require "groonga/client/response/log-reopen"
33
+ require "groonga/client/response/logical-range-filter"
34
+ require "groonga/client/response/logical-select"
33
35
  require "groonga/client/response/quit"
34
36
  require "groonga/client/response/register"
35
37
  require "groonga/client/response/schema"
@@ -19,6 +19,10 @@ require "csv"
19
19
  require "rexml/document"
20
20
  require "json"
21
21
 
22
+ begin
23
+ require "arrow"
24
+ rescue LoadError
25
+ end
22
26
  require "hashie"
23
27
 
24
28
  module Groonga
@@ -86,6 +90,9 @@ module Groonga
86
90
  when :tsv
87
91
  header, body = parse_tsv(raw_response)
88
92
  return_code = header["return_code"] if header
93
+ when :arrow, :"apache-arrow"
94
+ header, body = parse_apache_arrow(raw_response)
95
+ return_code = header["return_code"] if header
89
96
  else
90
97
  header = nil
91
98
  body = raw_response
@@ -177,6 +184,40 @@ module Groonga
177
184
  end
178
185
  body
179
186
  end
187
+
188
+ def parse_apache_arrow(response)
189
+ header = nil
190
+ body = nil
191
+ buffer = Arrow::Buffer.new(response)
192
+ Arrow::BufferInputStream.open(buffer) do |input|
193
+ while input.tell < response.bytesize
194
+ reader = Arrow::RecordBatchStreamReader.new(input)
195
+ schema = reader.schema
196
+ record_batches = reader.to_a
197
+ if apache_arrow_metadata?(schema)
198
+ table = Arrow::Table.new(schema, record_batches)
199
+ header = table.each_record.first.to_h
200
+ else
201
+ body = {}
202
+ body["columns"] = schema.fields.collect do |field|
203
+ [field.name, field.data_type.to_s]
204
+ end
205
+ if record_batches.empty?
206
+ records = []
207
+ else
208
+ table = Arrow::Table.new(schema, record_batches)
209
+ records = table.raw_records
210
+ end
211
+ body["records"] = records
212
+ end
213
+ end
214
+ end
215
+ return header, body
216
+ end
217
+
218
+ def apache_arrow_metadata?(schema)
219
+ (schema.metadata || {})["GROONGA:data_type"] == "metadata"
220
+ end
180
221
  end
181
222
 
182
223
  # @return [Groonga::Command] The command for the request.
@@ -0,0 +1,85 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ module Groonga
18
+ class Client
19
+ module Response
20
+ module Drilldownable
21
+ # @return [::Array<Groonga::Client::Response::Select::Drilldown>,
22
+ # ::Hash<String, Groonga::Client::Response::Select::Drilldown>]
23
+ # If labeled drilldowns are used or command version 3 or
24
+ # later is used, `{"label1" => drilldown1, "label2" => drilldown2}`
25
+ # is returned since 0.3.1.
26
+ #
27
+ # Otherwise, `[drilldown1, drilldown2]` is returned.
28
+ attr_accessor :drilldowns
29
+
30
+ private
31
+ def parse_drilldown(label, keys, raw_drilldown)
32
+ if raw_drilldown.is_a?(::Array)
33
+ n_hits = raw_drilldown[0][0]
34
+ raw_columns = raw_drilldown[1]
35
+ raw_records = raw_drilldown[2..-1]
36
+ else
37
+ n_hits = raw_drilldown["n_hits"]
38
+ raw_columns = raw_drilldown["columns"]
39
+ raw_records = raw_drilldown["records"]
40
+ end
41
+ records = parse_records(raw_columns, raw_records)
42
+ Drilldown.new(label,
43
+ keys,
44
+ n_hits,
45
+ records,
46
+ raw_columns,
47
+ raw_records)
48
+ end
49
+
50
+ def parse_drilldowns(keys, raw_drilldowns)
51
+ (raw_drilldowns || []).collect.with_index do |raw_drilldown, i|
52
+ key = keys[i]
53
+ parse_drilldown(key, [key], raw_drilldown)
54
+ end
55
+ end
56
+
57
+ def parse_labeled_drilldowns(labeled_drilldown_requests,
58
+ raw_drilldowns)
59
+ drilldowns = {}
60
+ (raw_drilldowns || {}).each do |label, raw_drilldown|
61
+ labeled_drilldown_request = labeled_drilldown_requests[label]
62
+ drilldowns[label] = parse_drilldown(label,
63
+ labeled_drilldown_request.keys,
64
+ raw_drilldown)
65
+ end
66
+ drilldowns
67
+ end
68
+
69
+ class Drilldown < Struct.new(:label,
70
+ :keys,
71
+ :n_hits,
72
+ :records,
73
+ :raw_columns,
74
+ :raw_records)
75
+ # @deprecated since 0.2.6. Use {#records} instead.
76
+ alias_method :items, :records
77
+
78
+ def key
79
+ keys.join(", ")
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "groonga/client/response/base"
18
+ require "groonga/client/response/searchable"
19
+
20
+ module Groonga
21
+ class Client
22
+ module Response
23
+ class LogicalRangeFilter < Base
24
+ Response.register("logical_range_filter", self)
25
+
26
+ include Searchable
27
+
28
+ attr_accessor :records
29
+
30
+ def body=(body)
31
+ super(body)
32
+ parse_body(body)
33
+ end
34
+
35
+ private
36
+ def parse_body(body)
37
+ if body.is_a?(::Array)
38
+ @raw_columns, *@raw_records = body.first
39
+ @raw_records ||= []
40
+ @records = parse_records(raw_columns, raw_records)
41
+ else
42
+ @raw_columns = body["columns"]
43
+ @raw_records = body["records"] || []
44
+ end
45
+ @records = parse_records(@raw_columns, @raw_records)
46
+ body
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+