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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c6eb335d9ea4011c1e5b3681dfd8e9252796b95d24c802df1a769757821b8bf
4
- data.tar.gz: 19824fe10455c126d229c1af171a8483ee67b15df08df78a9b8ec43dc0e661cd
3
+ metadata.gz: ad8ac6fe851f63509ad13e5c8abb1541ff2f47631764b86bc23ffc85719ae56a
4
+ data.tar.gz: 558bc6f1e08568791ca791a3be107b9f075864096bf003ca9cb37dc273a7479b
5
5
  SHA512:
6
- metadata.gz: b48b94c52345192fbb20ffbde0d450cd819ca97097b4b0a549ed285645f7a85278392ce51abefb29b055c8505aca5574789e0312fc81b6a7615eeed261e57933
7
- data.tar.gz: 2d58742abe16488dbcfcde075d9102b3988f27b58e8c398a60ba75406d0b17e11ac2ebf8d708c7ebe1b9e7b1a13adad0a59fdabaf646cd376c3463925f7f9f5c
6
+ metadata.gz: 9bde0f05e3d9a17f545bacad7cd6c91099ea65e1371d015860b5f18d714b31d875ba615b21ac6c8bba15333ce7f760b673c6ecf31e8daa8ebc726b79f53618a8
7
+ data.tar.gz: e992b6e14dac0073485a909886c128acca19af991a9d45dc89a57ed1557754a9ab5fe38edd687bcbd86a571dc0155264752b671cf1861e2353c9a12f40309507
data/doc/text/news.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # NEWS
2
2
 
3
+ ## 0.6.6 - 2021-12-10
4
+
5
+ ### Improvements
6
+
7
+ * `Groonga::Client::CommandProcessor`: Extracted Groonga command processor
8
+ from `groonga-client` command implementation.
9
+
3
10
  ## 0.6.5 - 2021-03-15
4
11
 
5
12
  ### Fixes
@@ -73,22 +73,11 @@ module Groonga
73
73
  end
74
74
  repl.run
75
75
  else
76
- $stdin.each_line do |line|
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
- File.open(command_file_path) do |command_file|
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 create_command_parser
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
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Groonga
18
18
  class Client
19
- VERSION = "0.6.5"
19
+ VERSION = "0.6.6"
20
20
  end
21
21
  end
@@ -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, :table => :Test, :name => :Body, :type => :ShortText) do
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, :table => :Test) do
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, :table => :Test, :values => values.to_json) do
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, :table => :Test) do
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, :name => :Test) do
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, :name => "Test")
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.5
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-03-15 00:00:00.000000000 Z
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