groonga-client 0.6.0 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/doc/text/news.md +47 -0
- data/groonga-client.gemspec +3 -2
- data/lib/groonga/client/command-line/groonga-client.rb +29 -2
- data/lib/groonga/client/protocol/http/synchronous.rb +45 -14
- data/lib/groonga/client/request/select.rb +1 -1
- data/lib/groonga/client/response.rb +3 -1
- data/lib/groonga/client/response/base.rb +41 -0
- data/lib/groonga/client/response/drilldownable.rb +85 -0
- data/lib/groonga/client/response/logical-range-filter.rb +52 -0
- data/lib/groonga/client/response/logical-select.rb +28 -0
- data/lib/groonga/client/response/searchable.rb +97 -0
- data/lib/groonga/client/response/select.rb +64 -125
- data/lib/groonga/client/version.rb +2 -2
- data/test/request/test-select.rb +2 -2
- data/test/response/test-select-command-version1.rb +58 -12
- data/test/response/test-select-command-version3.rb +54 -8
- data/test/response/test-select-tsv.rb +26 -4
- data/test/response/test-select-xml.rb +26 -4
- metadata +47 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c6eb335d9ea4011c1e5b3681dfd8e9252796b95d24c802df1a769757821b8bf
|
4
|
+
data.tar.gz: 19824fe10455c126d229c1af171a8483ee67b15df08df78a9b8ec43dc0e661cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/groonga-client.gemspec
CHANGED
@@ -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-
|
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.
|
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-
|
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
|
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-
|
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.
|
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
|
-
|
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?
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2014-
|
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
|
+
|