groonga-client 0.6.5 → 0.6.6
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 +7 -0
- data/lib/groonga/client/command-line/groonga-client.rb +4 -187
- data/lib/groonga/client/command-processor.rb +211 -0
- data/lib/groonga/client/version.rb +1 -1
- data/lib/groonga/client.rb +4 -3
- data/test/test-command.rb +7 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad8ac6fe851f63509ad13e5c8abb1541ff2f47631764b86bc23ffc85719ae56a
|
4
|
+
data.tar.gz: 558bc6f1e08568791ca791a3be107b9f075864096bf003ca9cb37dc273a7479b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bde0f05e3d9a17f545bacad7cd6c91099ea65e1371d015860b5f18d714b31d875ba615b21ac6c8bba15333ce7f760b673c6ecf31e8daa8ebc726b79f53618a8
|
7
|
+
data.tar.gz: e992b6e14dac0073485a909886c128acca19af991a9d45dc89a57ed1557754a9ab5fe38edd687bcbd86a571dc0155264752b671cf1861e2353c9a12f40309507
|
data/doc/text/news.md
CHANGED
@@ -73,22 +73,11 @@ module Groonga
|
|
73
73
|
end
|
74
74
|
repl.run
|
75
75
|
else
|
76
|
-
$stdin
|
77
|
-
runner << line
|
78
|
-
end
|
76
|
+
runner.consume($stdin)
|
79
77
|
end
|
80
78
|
else
|
81
79
|
command_file_paths.each do |command_file_path|
|
82
|
-
|
83
|
-
last_line = nil
|
84
|
-
command_file.each_line do |line|
|
85
|
-
last_line = line
|
86
|
-
runner << line
|
87
|
-
end
|
88
|
-
if last_line and !last_line.end_with?("\n")
|
89
|
-
runner << "\n"
|
90
|
-
end
|
91
|
-
end
|
80
|
+
runner.load(command_file_path)
|
92
81
|
end
|
93
82
|
end
|
94
83
|
runner.finish
|
@@ -173,95 +162,9 @@ module Groonga
|
|
173
162
|
end
|
174
163
|
end
|
175
164
|
|
176
|
-
class Runner
|
177
|
-
def initialize(client, options={})
|
178
|
-
@client = client
|
179
|
-
@split_load_chunk_size = options[:split_load_chunk_size] || 10000
|
180
|
-
@generate_request_id = options[:generate_request_id]
|
181
|
-
@target_commands = options[:target_commands]
|
182
|
-
@target_tables = options[:target_tables]
|
183
|
-
@target_columns = options[:target_columns]
|
184
|
-
@load_values = []
|
185
|
-
@parser = create_command_parser
|
186
|
-
end
|
187
|
-
|
188
|
-
def <<(line)
|
189
|
-
@parser << line
|
190
|
-
end
|
191
|
-
|
192
|
-
def finish
|
193
|
-
@parser.finish
|
194
|
-
end
|
195
|
-
|
196
|
-
def repl
|
197
|
-
begin
|
198
|
-
require "readline"
|
199
|
-
rescue LoadError
|
200
|
-
repl = BareREPL.new(self)
|
201
|
-
else
|
202
|
-
repl = ReadlineREPL.new(self)
|
203
|
-
repl_readline
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
165
|
+
class Runner < CommandProcessor
|
207
166
|
private
|
208
|
-
def
|
209
|
-
parser = Groonga::Command::Parser.new
|
210
|
-
|
211
|
-
parser.on_command do |command|
|
212
|
-
run_command(command)
|
213
|
-
end
|
214
|
-
|
215
|
-
parser.on_load_columns do |command, columns|
|
216
|
-
command[:columns] ||= columns.join(",")
|
217
|
-
end
|
218
|
-
|
219
|
-
parser.on_load_value do |command, value|
|
220
|
-
unless command[:values]
|
221
|
-
@load_values << value
|
222
|
-
if @load_values.size == @split_load_chunk_size
|
223
|
-
consume_load_values(command)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
command.original_source.clear
|
227
|
-
end
|
228
|
-
|
229
|
-
parser.on_load_complete do |command|
|
230
|
-
if command[:values]
|
231
|
-
run_command(command)
|
232
|
-
else
|
233
|
-
consume_load_values(command)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
parser
|
238
|
-
end
|
239
|
-
|
240
|
-
def consume_load_values(load_command)
|
241
|
-
return if @load_values.empty?
|
242
|
-
|
243
|
-
values_json = "["
|
244
|
-
@load_values.each_with_index do |value, i|
|
245
|
-
values_json << "," unless i.zero?
|
246
|
-
values_json << "\n"
|
247
|
-
values_json << JSON.generate(value)
|
248
|
-
end
|
249
|
-
values_json << "\n]\n"
|
250
|
-
load_command[:values] = values_json
|
251
|
-
run_command(load_command)
|
252
|
-
@load_values.clear
|
253
|
-
load_command[:values] = nil
|
254
|
-
end
|
255
|
-
|
256
|
-
def run_command(command)
|
257
|
-
return unless target_command?(command)
|
258
|
-
return unless target_table?(command)
|
259
|
-
return unless target_column?(command)
|
260
|
-
|
261
|
-
command = Marshal.load(Marshal.dump(command))
|
262
|
-
apply_target_columns(command)
|
263
|
-
command[:request_id] ||= SecureRandom.uuid if @generate_request_id
|
264
|
-
response = @client.execute(command)
|
167
|
+
def process_response(response, command)
|
265
168
|
case command.output_type
|
266
169
|
when :json
|
267
170
|
puts(JSON.pretty_generate([response.header, response.body]))
|
@@ -271,92 +174,6 @@ module Groonga
|
|
271
174
|
puts(response.body)
|
272
175
|
end
|
273
176
|
end
|
274
|
-
|
275
|
-
def target_command?(command)
|
276
|
-
return true if @target_commands.empty?
|
277
|
-
|
278
|
-
@target_commands.any? do |name|
|
279
|
-
name === command.command_name
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def target_table?(command)
|
284
|
-
return true if @target_tables.empty?
|
285
|
-
|
286
|
-
target = nil
|
287
|
-
case command.command_name
|
288
|
-
when "load", "column_create", "select"
|
289
|
-
target = command.table
|
290
|
-
when "table_create", "table_remove"
|
291
|
-
target = command.name
|
292
|
-
end
|
293
|
-
return true if target.nil?
|
294
|
-
|
295
|
-
@target_tables.any? do |name|
|
296
|
-
name === target
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
def target_column?(command)
|
301
|
-
return true if @target_columns.empty?
|
302
|
-
|
303
|
-
target = nil
|
304
|
-
case command.command_name
|
305
|
-
when "column_create"
|
306
|
-
target = command.name
|
307
|
-
end
|
308
|
-
return true if target.nil?
|
309
|
-
|
310
|
-
@target_columns.any? do |name|
|
311
|
-
name === target
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
def apply_target_columns(command)
|
316
|
-
return if @target_columns.empty?
|
317
|
-
|
318
|
-
values = command[:values]
|
319
|
-
return if values.nil?
|
320
|
-
|
321
|
-
command = command.dup
|
322
|
-
|
323
|
-
values = JSON.parse(values)
|
324
|
-
columns = command[:columns]
|
325
|
-
if columns
|
326
|
-
columns = columns.split(/\s*,\s*/)
|
327
|
-
target_indexes = []
|
328
|
-
new_columns = []
|
329
|
-
columns.each_with_index do |column, i|
|
330
|
-
if load_target_column?(column)
|
331
|
-
target_indexes << i
|
332
|
-
new_columns << column
|
333
|
-
end
|
334
|
-
end
|
335
|
-
command[:columns] = new_columns.join(",")
|
336
|
-
new_values = values.collect do |value|
|
337
|
-
target_indexes.collect do |i|
|
338
|
-
value[i]
|
339
|
-
end
|
340
|
-
end
|
341
|
-
command[:values] = JSON.generate(new_values)
|
342
|
-
else
|
343
|
-
new_values = values.collect do |value|
|
344
|
-
new_value = {}
|
345
|
-
value.each do |key, value|
|
346
|
-
if load_target_column?(key)
|
347
|
-
new_value[key] = value
|
348
|
-
end
|
349
|
-
end
|
350
|
-
new_value
|
351
|
-
end
|
352
|
-
command[:values] = JSON.generate(new_values)
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
def load_target_column?(column)
|
357
|
-
column == "_key" or
|
358
|
-
@target_columns.any? {|name| name === column}
|
359
|
-
end
|
360
177
|
end
|
361
178
|
|
362
179
|
class BareREPL
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# Copyright (C) 2015-2021 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 "json"
|
18
|
+
|
19
|
+
require "groonga/command/parser"
|
20
|
+
|
21
|
+
module Groonga
|
22
|
+
class Client
|
23
|
+
class CommandProcessor
|
24
|
+
def initialize(client, options={})
|
25
|
+
@client = client
|
26
|
+
@split_load_chunk_size = options[:split_load_chunk_size] || 10000
|
27
|
+
@generate_request_id = options[:generate_request_id]
|
28
|
+
@target_commands = options[:target_commands]
|
29
|
+
@target_tables = options[:target_tables]
|
30
|
+
@target_columns = options[:target_columns]
|
31
|
+
@load_values = []
|
32
|
+
@parser = create_command_parser
|
33
|
+
end
|
34
|
+
|
35
|
+
def <<(line)
|
36
|
+
@parser << line
|
37
|
+
end
|
38
|
+
|
39
|
+
def finish
|
40
|
+
@parser.finish
|
41
|
+
end
|
42
|
+
|
43
|
+
def consume(input)
|
44
|
+
last_line = nil
|
45
|
+
input.each_line do |line|
|
46
|
+
last_line = line
|
47
|
+
@parser << line
|
48
|
+
end
|
49
|
+
if last_line and last_line.end_with?("\n")
|
50
|
+
@parser << "\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def load(path)
|
55
|
+
File.open(path) do |input|
|
56
|
+
consume(input)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def create_command_parser
|
62
|
+
parser = Groonga::Command::Parser.new
|
63
|
+
|
64
|
+
parser.on_command do |command|
|
65
|
+
run_command(command)
|
66
|
+
end
|
67
|
+
|
68
|
+
parser.on_load_columns do |command, columns|
|
69
|
+
command[:columns] ||= columns.join(",")
|
70
|
+
end
|
71
|
+
|
72
|
+
parser.on_load_value do |command, value|
|
73
|
+
unless command[:values]
|
74
|
+
@load_values << value
|
75
|
+
if @load_values.size == @split_load_chunk_size
|
76
|
+
consume_load_values(command)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
command.original_source.clear
|
80
|
+
end
|
81
|
+
|
82
|
+
parser.on_load_complete do |command|
|
83
|
+
if command[:values]
|
84
|
+
run_command(command)
|
85
|
+
else
|
86
|
+
consume_load_values(command)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
parser
|
91
|
+
end
|
92
|
+
|
93
|
+
def consume_load_values(load_command)
|
94
|
+
return if @load_values.empty?
|
95
|
+
|
96
|
+
values_json = "["
|
97
|
+
@load_values.each_with_index do |value, i|
|
98
|
+
values_json << "," unless i.zero?
|
99
|
+
values_json << "\n"
|
100
|
+
values_json << JSON.generate(value)
|
101
|
+
end
|
102
|
+
values_json << "\n]\n"
|
103
|
+
load_command[:values] = values_json
|
104
|
+
run_command(load_command)
|
105
|
+
@load_values.clear
|
106
|
+
load_command[:values] = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def run_command(command)
|
110
|
+
return unless target_command?(command)
|
111
|
+
return unless target_table?(command)
|
112
|
+
return unless target_column?(command)
|
113
|
+
|
114
|
+
command = Marshal.load(Marshal.dump(command))
|
115
|
+
apply_target_columns(command)
|
116
|
+
command[:request_id] ||= SecureRandom.uuid if @generate_request_id
|
117
|
+
response = @client.execute(command)
|
118
|
+
process_response(response, command)
|
119
|
+
end
|
120
|
+
|
121
|
+
def process_response(response, command)
|
122
|
+
end
|
123
|
+
|
124
|
+
def target_command?(command)
|
125
|
+
return true if @target_commands.empty?
|
126
|
+
|
127
|
+
@target_commands.any? do |name|
|
128
|
+
name === command.command_name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def target_table?(command)
|
133
|
+
return true if @target_tables.empty?
|
134
|
+
|
135
|
+
target = nil
|
136
|
+
case command.command_name
|
137
|
+
when "load", "column_create", "select"
|
138
|
+
target = command.table
|
139
|
+
when "table_create", "table_remove"
|
140
|
+
target = command.name
|
141
|
+
end
|
142
|
+
return true if target.nil?
|
143
|
+
|
144
|
+
@target_tables.any? do |name|
|
145
|
+
name === target
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def target_column?(command)
|
150
|
+
return true if @target_columns.empty?
|
151
|
+
|
152
|
+
target = nil
|
153
|
+
case command.command_name
|
154
|
+
when "column_create"
|
155
|
+
target = command.name
|
156
|
+
end
|
157
|
+
return true if target.nil?
|
158
|
+
|
159
|
+
@target_columns.any? do |name|
|
160
|
+
name === target
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def apply_target_columns(command)
|
165
|
+
return if @target_columns.empty?
|
166
|
+
|
167
|
+
values = command[:values]
|
168
|
+
return if values.nil?
|
169
|
+
|
170
|
+
command = command.dup
|
171
|
+
|
172
|
+
values = JSON.parse(values)
|
173
|
+
columns = command[:columns]
|
174
|
+
if columns
|
175
|
+
columns = columns.split(/\s*,\s*/)
|
176
|
+
target_indexes = []
|
177
|
+
new_columns = []
|
178
|
+
columns.each_with_index do |column, i|
|
179
|
+
if load_target_column?(column)
|
180
|
+
target_indexes << i
|
181
|
+
new_columns << column
|
182
|
+
end
|
183
|
+
end
|
184
|
+
command[:columns] = new_columns.join(",")
|
185
|
+
new_values = values.collect do |value|
|
186
|
+
target_indexes.collect do |i|
|
187
|
+
value[i]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
command[:values] = JSON.generate(new_values)
|
191
|
+
else
|
192
|
+
new_values = values.collect do |value|
|
193
|
+
new_value = {}
|
194
|
+
value.each do |key, value|
|
195
|
+
if load_target_column?(key)
|
196
|
+
new_value[key] = value
|
197
|
+
end
|
198
|
+
end
|
199
|
+
new_value
|
200
|
+
end
|
201
|
+
command[:values] = JSON.generate(new_values)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def load_target_column?(column)
|
206
|
+
column == "_key" or
|
207
|
+
@target_columns.any? {|name| name === column}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
data/lib/groonga/client.rb
CHANGED
@@ -18,12 +18,13 @@
|
|
18
18
|
require "uri"
|
19
19
|
require "json"
|
20
20
|
|
21
|
-
require "groonga/client/default"
|
22
21
|
require "groonga/client/command"
|
22
|
+
require "groonga/client/command-processor"
|
23
|
+
require "groonga/client/default"
|
23
24
|
require "groonga/client/empty-request"
|
25
|
+
require "groonga/client/protocol/file"
|
24
26
|
require "groonga/client/protocol/gqtp"
|
25
27
|
require "groonga/client/protocol/http"
|
26
|
-
require "groonga/client/protocol/file"
|
27
28
|
require "groonga/client/request"
|
28
29
|
|
29
30
|
module Groonga
|
@@ -202,7 +203,7 @@ module Groonga
|
|
202
203
|
end
|
203
204
|
|
204
205
|
def method_missing(name, *args, &block)
|
205
|
-
if groonga_command_name?(name)
|
206
|
+
if groonga_command_name?(name) and args.size <= 1
|
206
207
|
execute(name, *args, &block)
|
207
208
|
else
|
208
209
|
super
|
data/test/test-command.rb
CHANGED
@@ -5,7 +5,8 @@ class TestCommand < Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
def test_column_create
|
7
7
|
response = Object.new
|
8
|
-
mock(@client).execute(:column_create,
|
8
|
+
mock(@client).execute(:column_create,
|
9
|
+
{table: :Test, name: :Body, type: :ShortText}) do
|
9
10
|
response
|
10
11
|
end
|
11
12
|
@client.column_create(:table => :Test, :name => :Body, :type => :ShortText)
|
@@ -13,7 +14,7 @@ class TestCommand < Test::Unit::TestCase
|
|
13
14
|
|
14
15
|
def test_column_list
|
15
16
|
response = Object.new
|
16
|
-
mock(@client).execute(:column_list, :
|
17
|
+
mock(@client).execute(:column_list, {table: :Test}) do
|
17
18
|
response
|
18
19
|
end
|
19
20
|
@client.column_list(:table => :Test)
|
@@ -27,7 +28,7 @@ class TestCommand < Test::Unit::TestCase
|
|
27
28
|
}
|
28
29
|
]
|
29
30
|
response = Object.new
|
30
|
-
mock(@client).execute(:load, :
|
31
|
+
mock(@client).execute(:load, {table: :Test, values: values.to_json}) do
|
31
32
|
response
|
32
33
|
end
|
33
34
|
@client.load(:table => :Test, :values => values.to_json)
|
@@ -35,7 +36,7 @@ class TestCommand < Test::Unit::TestCase
|
|
35
36
|
|
36
37
|
def test_select
|
37
38
|
response = Object.new
|
38
|
-
mock(@client).execute(:select, :
|
39
|
+
mock(@client).execute(:select, {table: :Test}) do
|
39
40
|
response
|
40
41
|
end
|
41
42
|
@client.select(:table => :Test)
|
@@ -43,7 +44,7 @@ class TestCommand < Test::Unit::TestCase
|
|
43
44
|
|
44
45
|
def test_table_create
|
45
46
|
response = Object.new
|
46
|
-
mock(@client).execute(:table_create, :
|
47
|
+
mock(@client).execute(:table_create, {name: :Test}) do
|
47
48
|
response
|
48
49
|
end
|
49
50
|
@client.table_create(:name => :Test)
|
@@ -58,7 +59,7 @@ class TestCommand < Test::Unit::TestCase
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def test_table_remove
|
61
|
-
mock(@client).execute(:table_remove, :
|
62
|
+
mock(@client).execute(:table_remove, {name: "Test"})
|
62
63
|
@client.table_remove(:name => "Test")
|
63
64
|
end
|
64
65
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groonga-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Haruka Yoshihara
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-12-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: gqtp
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- lib/groonga/client/command-line/groonga-client.rb
|
198
198
|
- lib/groonga/client/command-line/parser.rb
|
199
199
|
- lib/groonga/client/command-line/runner.rb
|
200
|
+
- lib/groonga/client/command-processor.rb
|
200
201
|
- lib/groonga/client/command.rb
|
201
202
|
- lib/groonga/client/default.rb
|
202
203
|
- lib/groonga/client/empty-request.rb
|