groonga-client 0.5.2 → 0.5.3

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.
@@ -1,16 +1,142 @@
1
+ # Copyright (C) 2013 Kosuke Asami
2
+ # Copyright (C) 2017 Kouhei Sutou <kou@clear-code.com>
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
1
18
  require "response/helper"
2
19
 
3
20
  class TestResponseColumnList < Test::Unit::TestCase
4
- include TestResponseHelper
21
+ class TestParse < self
22
+ include TestResponseHelper
23
+
24
+ def column(attributes)
25
+ c = Groonga::Client::Response::ColumnList::Column.new
26
+ attributes.each do |name, value|
27
+ c[name] = value
28
+ end
29
+ c
30
+ end
31
+
32
+ def test_parse
33
+ header = [0, 1372430096.70991, 0.000522851943969727]
34
+ body = [
35
+ [
36
+ ["id", "UInt32"],
37
+ ["name", "ShortText"],
38
+ ["path", "ShortText"],
39
+ ["type", "ShortText"],
40
+ ["flags", "ShortText"],
41
+ ["domain", "ShortText"],
42
+ ["range", "ShortText"],
43
+ ["source", "ShortText"],
44
+ ],
45
+ [
46
+ 256,
47
+ "content",
48
+ "/tmp/test.db.0000100",
49
+ "var",
50
+ "COLUMN_SCALAR|PERSISTENT",
51
+ "TestTable",
52
+ "ShortText",
53
+ [],
54
+ ],
55
+ ]
56
+ raw_response = [header, body].to_json
57
+
58
+ response = parse_raw_response("column_list", raw_response)
59
+ assert_equal([
60
+ column(:id => 256,
61
+ :name => "content",
62
+ :path => "/tmp/test.db.0000100",
63
+ :type => "var",
64
+ :flags => "COLUMN_SCALAR|PERSISTENT",
65
+ :domain => "TestTable",
66
+ :range => "ShortText",
67
+ :source => []),
68
+ ],
69
+ response.to_a)
70
+ end
71
+ end
72
+
73
+ class TestBody < self
74
+ def setup
75
+ @command = Groonga::Command::Base.new("column_list", "table" => "Memos")
76
+ end
77
+
78
+ def create_response(columns)
79
+ header = [0, 1372430096.70991, 0.000522851943969727]
80
+ body = [
81
+ [
82
+ ["id", "UInt32"],
83
+ ["name", "ShortText"],
84
+ ["path", "ShortText"],
85
+ ["type", "ShortText"],
86
+ ["flags", "ShortText"],
87
+ ["domain", "ShortText"],
88
+ ["range", "ShortText"],
89
+ ["source", "ShortText"],
90
+ ],
91
+ *columns,
92
+ ]
93
+ Groonga::Client::Response::ColumnList.new(@command, header, body)
94
+ end
95
+
96
+ class TestFlags < self
97
+ def create_response(flags)
98
+ columns = [
99
+ [
100
+ 256,
101
+ "content",
102
+ "/tmp/test.db.0000100",
103
+ "var",
104
+ flags,
105
+ "Memos",
106
+ "ShortText",
107
+ [],
108
+ ]
109
+ ]
110
+ super(columns)
111
+ end
112
+
113
+ def test_multiple
114
+ response = create_response("COLUMN_SCALAR|PERSISTENT")
115
+ assert_equal(["COLUMN_SCALAR", "PERSISTENT"],
116
+ response[0].flags)
117
+ end
118
+
119
+ def test_scalar?
120
+ response = create_response("COLUMN_SCALAR|PERSISTENT")
121
+ assert do
122
+ response[0].scalar?
123
+ end
124
+ end
5
125
 
6
- def test_column_list
7
- header = [0,1372430096.70991,0.000522851943969727]
8
- body = [[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],
9
- [256,"Text","/tmp/test.db.0000100","var","COLUMN_SCALAR|PERSISTENT","TestTable","ShortText",[]]]
10
- raw_response = [header, body].to_json
126
+ def test_vector?
127
+ response = create_response("COLUMN_VECTOR|PERSISTENT")
128
+ assert do
129
+ response[0].vector?
130
+ end
131
+ end
11
132
 
12
- response = parse_raw_response("column_list", raw_response)
13
- assert_equal(Groonga::Client::Response::ColumnList, response.class)
133
+ def test_index?
134
+ response = create_response("COLUMN_INDEX|WITH_POSITION|PERSISTENT")
135
+ assert do
136
+ response[0].index?
137
+ end
138
+ end
139
+ end
14
140
  end
15
141
  end
16
142
 
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2016 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2016-2017 Kouhei Sutou <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
@@ -20,7 +20,7 @@ class TestResponseSchema < Test::Unit::TestCase
20
20
  class TestParseRawResponse < self
21
21
  include TestResponseHelper
22
22
 
23
- def test_select
23
+ def test_parse
24
24
  header = [0, 1372430096.70991, 0.000522851943969727]
25
25
  body = {}
26
26
  raw_response = [header, body].to_json
@@ -40,6 +40,139 @@ class TestResponseSchema < Test::Unit::TestCase
40
40
  Groonga::Client::Response::Schema.new(@command, header, body)
41
41
  end
42
42
 
43
+ class TestReferenceShortCut < self
44
+ def test_plugin
45
+ body = {
46
+ "plugins" => {
47
+ "token_filters/stop_word" => {
48
+ "name" => "token_filters/stop_word",
49
+ },
50
+ },
51
+ "types" => {},
52
+ "tokenizers" => {},
53
+ "normalizers" => {},
54
+ "token_filters" => {},
55
+ "tables" => {},
56
+ }
57
+ response = create_response(body)
58
+ assert_equal({"name" => "token_filters/stop_word"},
59
+ response["token_filters/stop_word"])
60
+ end
61
+
62
+ def test_type
63
+ body = {
64
+ "plugins" => {},
65
+ "types" => {
66
+ "ShortText" => {
67
+ "name" => "ShortText",
68
+ },
69
+ },
70
+ "tokenizers" => {},
71
+ "normalizers" => {},
72
+ "token_filters" => {},
73
+ "tables" => {},
74
+ }
75
+ response = create_response(body)
76
+ assert_equal({"name" => "ShortText"},
77
+ response["ShortText"])
78
+ end
79
+
80
+ def test_tokenizer
81
+ body = {
82
+ "plugins" => {},
83
+ "types" => {},
84
+ "tokenizers" => {
85
+ "TokenBigram" => {
86
+ "name" => "TokenBigram",
87
+ },
88
+ },
89
+ "normalizers" => {},
90
+ "token_filters" => {},
91
+ "tables" => {},
92
+ }
93
+ response = create_response(body)
94
+ assert_equal({"name" => "TokenBigram"},
95
+ response["TokenBigram"])
96
+ end
97
+
98
+ def test_normalizer
99
+ body = {
100
+ "plugins" => {},
101
+ "types" => {},
102
+ "tokenizers" => {},
103
+ "normalizers" => {
104
+ "NormalizerAuto" => {
105
+ "name" => "NormalizerAuto",
106
+ },
107
+ },
108
+ "token_filters" => {},
109
+ "tables" => {},
110
+ }
111
+ response = create_response(body)
112
+ assert_equal({"name" => "NormalizerAuto"},
113
+ response["NormalizerAuto"])
114
+ end
115
+
116
+ def test_token_filters
117
+ body = {
118
+ "plugins" => {},
119
+ "types" => {},
120
+ "tokenizers" => {},
121
+ "normalizers" => {},
122
+ "token_filters" => {
123
+ "TokenFilterStopWord" => {
124
+ "name" => "TokenFilterStopWord",
125
+ },
126
+ },
127
+ "tables" => {},
128
+ }
129
+ response = create_response(body)
130
+ assert_equal({"name" => "TokenFilterStopWord"},
131
+ response["TokenFilterStopWord"])
132
+ end
133
+
134
+ def test_table
135
+ body = {
136
+ "plugins" => {},
137
+ "types" => {},
138
+ "tokenizers" => {},
139
+ "normalizers" => {},
140
+ "token_filters" => {},
141
+ "tables" => {
142
+ "Users" => {
143
+ "name" => "Users",
144
+ },
145
+ },
146
+ }
147
+ response = create_response(body)
148
+ assert_equal({"name" => "Users"},
149
+ response["Users"])
150
+ end
151
+
152
+ def test_column
153
+ body = {
154
+ "plugins" => {},
155
+ "types" => {},
156
+ "tokenizers" => {},
157
+ "normalizers" => {},
158
+ "token_filters" => {},
159
+ "tables" => {
160
+ "Users" => {
161
+ "name" => "Users",
162
+ "columns" => {
163
+ "age" => {
164
+ "name" => "age",
165
+ },
166
+ },
167
+ },
168
+ },
169
+ }
170
+ response = create_response(body)
171
+ assert_equal({"name" => "age"},
172
+ response["Users.age"])
173
+ end
174
+ end
175
+
43
176
  class TestTable < self
44
177
  def test_key_type
45
178
  body = {
@@ -263,6 +396,30 @@ class TestResponseSchema < Test::Unit::TestCase
263
396
  end
264
397
  end
265
398
  end
399
+
400
+ def test_command
401
+ body = {
402
+ "tables" => {
403
+ "Users" => {
404
+ "command" => {
405
+ "name" => "table_create",
406
+ "arguments" => {
407
+ "name" => "Users",
408
+ "flags" => "TABLE_HASH_KEY",
409
+ "key_type" => "ShortText",
410
+ },
411
+ }
412
+ }
413
+ }
414
+ }
415
+ response = create_response(body)
416
+ assert_equal({
417
+ "name" => "Users",
418
+ "flags" => "TABLE_HASH_KEY",
419
+ "key_type" => "ShortText",
420
+ },
421
+ response.tables["Users"].command.arguments)
422
+ end
266
423
  end
267
424
 
268
425
  class TestColumn < self
@@ -410,6 +567,36 @@ class TestResponseSchema < Test::Unit::TestCase
410
567
  end
411
568
  end
412
569
  end
570
+
571
+ def test_command
572
+ body = {
573
+ "tables" => {
574
+ "Users" => {
575
+ "columns" => {
576
+ "name" => {
577
+ "command" => {
578
+ "name" => "column_create",
579
+ "arguments" => {
580
+ "table" => "Users",
581
+ "name" => "name",
582
+ "flags" => "COLUMN_SCALAR",
583
+ "type" => "ShortText",
584
+ },
585
+ }
586
+ }
587
+ }
588
+ }
589
+ }
590
+ }
591
+ response = create_response(body)
592
+ assert_equal({
593
+ "table" => "Users",
594
+ "name" => "name",
595
+ "flags" => "COLUMN_SCALAR",
596
+ "type" => "ShortText",
597
+ },
598
+ response.tables["Users"].columns["name"].command.arguments)
599
+ end
413
600
  end
414
601
 
415
602
  class TestIndex < self
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.5.2
4
+ version: 0.5.3
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: 2017-09-27 00:00:00.000000000 Z
13
+ date: 2017-10-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gqtp
@@ -161,6 +161,7 @@ email:
161
161
  - kou@clear-code.com
162
162
  - tfortress58@gmail.com
163
163
  executables:
164
+ - groonga-client-index-recreate
164
165
  - groonga-client
165
166
  extensions: []
166
167
  extra_rdoc_files: []
@@ -170,11 +171,13 @@ files:
170
171
  - README.md
171
172
  - Rakefile
172
173
  - bin/groonga-client
174
+ - bin/groonga-client-index-recreate
173
175
  - doc/text/lgpl-2.1.txt
174
176
  - doc/text/news.md
175
177
  - groonga-client.gemspec
176
178
  - lib/groonga/client.rb
177
- - lib/groonga/client/cli.rb
179
+ - lib/groonga/client/command-line/groonga-client-index-recreate.rb
180
+ - lib/groonga/client/command-line/groonga-client.rb
178
181
  - lib/groonga/client/command.rb
179
182
  - lib/groonga/client/default.rb
180
183
  - lib/groonga/client/empty-request.rb
@@ -221,6 +224,7 @@ files:
221
224
  - lib/groonga/client/test/fixture.rb
222
225
  - lib/groonga/client/test/groonga-server-runner.rb
223
226
  - lib/groonga/client/version.rb
227
+ - test/command-line/test-index-recreate.rb
224
228
  - test/protocol/test-gqtp.rb
225
229
  - test/protocol/test-http.rb
226
230
  - test/request/select/test-backward-compatible-sort-keys-parameter.rb
@@ -245,7 +249,6 @@ files:
245
249
  - test/response/test-table-create.rb
246
250
  - test/response/test-table-list.rb
247
251
  - test/response/test-table-remove.rb
248
- - test/results/test-column-list.rb
249
252
  - test/results/test-table-list.rb
250
253
  - test/run-test.rb
251
254
  - test/test-client.rb
@@ -271,13 +274,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
274
  version: '0'
272
275
  requirements: []
273
276
  rubyforge_project:
274
- rubygems_version: 2.5.2
277
+ rubygems_version: 2.5.2.1
275
278
  signing_key:
276
279
  specification_version: 4
277
280
  summary: Groonga-client is a client for Groonga (http://groonga.org/) implemented
278
281
  with pure Ruby. You can use it without Groonga.
279
282
  test_files:
280
283
  - test/test-client.rb
284
+ - test/command-line/test-index-recreate.rb
281
285
  - test/test-script-syntax.rb
282
286
  - test/request/select/test-backward-compatible-sort-keys-parameter.rb
283
287
  - test/request/select/test-filter.rb
@@ -305,5 +309,4 @@ test_files:
305
309
  - test/response/test-select-command-version1.rb
306
310
  - test/response/test-table-create.rb
307
311
  - test/response/test-table-remove.rb
308
- - test/results/test-column-list.rb
309
312
  - test/results/test-table-list.rb
@@ -1,233 +0,0 @@
1
- # Copyright (C) 2015-2016 Kouhei Sutou <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 "ostruct"
18
- require "optparse"
19
- require "json"
20
- require "securerandom"
21
-
22
- require "groonga/client"
23
-
24
- require "groonga/command/parser"
25
-
26
- module Groonga
27
- class Client
28
- class CLI
29
- def initialize
30
- @protocol = :http
31
- @host = "localhost"
32
- @port = nil
33
-
34
- @read_timeout = Client::Default::READ_TIMEOUT
35
-
36
- @chunk = false
37
-
38
- @runner_options = {
39
- :split_load_chunk_size => 10000,
40
- :generate_request_id => false,
41
- }
42
- end
43
-
44
- def run(argv)
45
- command_file_paths = parse_command_line(argv)
46
-
47
- @client = Client.new(:protocol => @protocol,
48
- :host => @host,
49
- :port => @port,
50
- :read_timeout => @read_timeout,
51
- :chunk => @chunk,
52
- :backend => :synchronous)
53
- runner = Runner.new(@client, @runner_options)
54
-
55
- if command_file_paths.empty?
56
- $stdin.each_line do |line|
57
- runner << line
58
- end
59
- else
60
- command_file_paths.each do |command_file_path|
61
- File.open(command_file_path) do |command_file|
62
- last_line = nil
63
- command_file.each_line do |line|
64
- last_line = line
65
- runner << line
66
- end
67
- if last_line and !last_line.end_with?("\n")
68
- runner << "\n"
69
- end
70
- end
71
- end
72
- end
73
- runner.finish
74
-
75
- true
76
- end
77
-
78
- private
79
- def parse_command_line(argv)
80
- parser = OptionParser.new
81
- parser.version = VERSION
82
- parser.banner += " GROONGA_COMMAND_FILE1 GROONGA_COMMAND_FILE2 ..."
83
-
84
- parser.separator("")
85
-
86
- parser.separator("Connection:")
87
-
88
- available_protocols = [:http, :gqtp]
89
- parser.on("--protocol=PROTOCOL", [:http, :gqtp],
90
- "Protocol to connect to Groonga server.",
91
- "[#{available_protocols.join(", ")}]",
92
- "(#{@protocol})") do |protocol|
93
- @protocol = protocol
94
- end
95
-
96
- parser.on("--host=HOST",
97
- "Groonga server to be connected.",
98
- "(#{@host})") do |host|
99
- @host = host
100
- end
101
-
102
- parser.on("--port=PORT", Integer,
103
- "Port number of Groonga server to be connected.",
104
- "(auto)") do |port|
105
- @port = port
106
- end
107
-
108
- parser.on("--read-timeout=TIMEOUT", Integer,
109
- "Timeout on reading response from Groonga server.",
110
- "You can disable timeout by specifying -1.",
111
- "(#{@read_timeout})") do |timeout|
112
- @read_timeout = timeout
113
- end
114
-
115
- parser.on("--split-load-chunk-size=SIZE", Integer,
116
- "Split a large load to small loads.",
117
- "Each small load has at most SIZE records.",
118
- "Set 0 to SIZE to disable this feature.",
119
- "(#{@runner_options[:split_load_chunk_size]})") do |size|
120
- @runner_options[:split_load_chunk_size] = size
121
- end
122
-
123
- parser.on("--[no-]generate-request-id",
124
- "Add auto generated request ID to all commands.",
125
- "(#{@runner_options[:generate_request_id]})") do |boolean|
126
- @runner_options[:generate_request_id] = boolean
127
- end
128
-
129
- parser.on("--[no-]chunk",
130
- "Use \"Transfer-Encoding: chunked\" for load command.",
131
- "HTTP only.",
132
- "(#{@chunk})") do |boolean|
133
- @chunk = boolean
134
- end
135
-
136
- command_file_paths = parser.parse(argv)
137
-
138
- @port ||= default_port(@protocol)
139
-
140
- command_file_paths
141
- end
142
-
143
- def default_port(protocol)
144
- case protocol
145
- when :http
146
- 10041
147
- when :gqtp
148
- 10043
149
- end
150
- end
151
-
152
- class Runner
153
- def initialize(client, options={})
154
- @client = client
155
- @split_load_chunk_size = options[:split_load_chunk_size] || 10000
156
- @generate_request_id = options[:generate_request_id]
157
- @load_values = []
158
- @parser = create_command_parser
159
- end
160
-
161
- def <<(line)
162
- @parser << line
163
- end
164
-
165
- def finish
166
- @parser.finish
167
- end
168
-
169
- private
170
- def create_command_parser
171
- parser = Groonga::Command::Parser.new
172
-
173
- parser.on_command do |command|
174
- run_command(command)
175
- end
176
-
177
- parser.on_load_columns do |command, columns|
178
- command[:columns] ||= columns.join(",")
179
- end
180
-
181
- parser.on_load_value do |command, value|
182
- unless command[:values]
183
- @load_values << value
184
- if @load_values.size == @split_load_chunk_size
185
- consume_load_values(command)
186
- end
187
- end
188
- command.original_source.clear
189
- end
190
-
191
- parser.on_load_complete do |command|
192
- if command[:values]
193
- run_command(command)
194
- else
195
- consume_load_values(command)
196
- end
197
- end
198
-
199
- parser
200
- end
201
-
202
- def consume_load_values(load_command)
203
- return if @load_values.empty?
204
-
205
- values_json = "["
206
- @load_values.each_with_index do |value, i|
207
- values_json << "," unless i.zero?
208
- values_json << "\n"
209
- values_json << JSON.generate(value)
210
- end
211
- values_json << "\n]\n"
212
- load_command[:values] = values_json
213
- run_command(load_command)
214
- @load_values.clear
215
- load_command[:values] = nil
216
- end
217
-
218
- def run_command(command)
219
- command[:request_id] ||= SecureRandom.uuid if @generate_request_id
220
- response = @client.execute(command)
221
- case command.output_type
222
- when :json
223
- puts(JSON.pretty_generate([response.header, response.body]))
224
- when :xml
225
- puts(response.raw)
226
- else
227
- puts(response.body)
228
- end
229
- end
230
- end
231
- end
232
- end
233
- end