groonga-client 0.5.4 → 0.5.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.
@@ -14,26 +14,19 @@
14
14
  # License along with this library; if not, write to the Free Software
15
15
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
- require "optparse"
18
17
  require "json"
19
18
  require "securerandom"
20
19
 
21
- require "groonga/client"
22
-
23
20
  require "groonga/command/parser"
24
21
 
22
+ require "groonga/client"
23
+ require "groonga/client/command-line/parser"
24
+
25
25
  module Groonga
26
26
  class Client
27
27
  module CommandLine
28
28
  class GroongaClient
29
29
  def initialize
30
- @url = nil
31
- @protocol = :http
32
- @host = "localhost"
33
- @port = nil
34
-
35
- @read_timeout = Client::Default::READ_TIMEOUT
36
-
37
30
  @chunk = false
38
31
 
39
32
  @runner_options = {
@@ -42,16 +35,13 @@ module Groonga
42
35
  }
43
36
  end
44
37
 
45
- def run(argv)
46
- command_file_paths = parse_command_line(argv)
38
+ def run(arguments)
39
+ parser = Parser.new
40
+ command_file_paths = parser.parse(arguments) do |option_parser|
41
+ parse_command_line(option_parser)
42
+ end
47
43
 
48
- Client.open(:url => @url,
49
- :protocol => @protocol,
50
- :host => @host,
51
- :port => @port,
52
- :read_timeout => @read_timeout,
53
- :chunk => @chunk,
54
- :backend => :synchronous) do |client|
44
+ parser.open_client(:chunk => @chunk) do |client|
55
45
  runner = Runner.new(client, @runner_options)
56
46
 
57
47
  if command_file_paths.empty?
@@ -79,48 +69,11 @@ module Groonga
79
69
  end
80
70
 
81
71
  private
82
- def parse_command_line(argv)
83
- parser = OptionParser.new
84
- parser.version = VERSION
72
+ def parse_command_line(parser)
85
73
  parser.banner += " GROONGA_COMMAND_FILE1 GROONGA_COMMAND_FILE2 ..."
86
74
 
87
75
  parser.separator("")
88
-
89
- parser.separator("Connection:")
90
-
91
- parser.on("--url=URL",
92
- "URL to connect to Groonga server.",
93
- "If this option is specified,",
94
- "--protocol, --host and --port are ignored.") do |url|
95
- @url = url
96
- end
97
-
98
- available_protocols = [:http, :gqtp]
99
- parser.on("--protocol=PROTOCOL", [:http, :gqtp],
100
- "Protocol to connect to Groonga server.",
101
- "[#{available_protocols.join(", ")}]",
102
- "(#{@protocol})") do |protocol|
103
- @protocol = protocol
104
- end
105
-
106
- parser.on("--host=HOST",
107
- "Groonga server to be connected.",
108
- "(#{@host})") do |host|
109
- @host = host
110
- end
111
-
112
- parser.on("--port=PORT", Integer,
113
- "Port number of Groonga server to be connected.",
114
- "(auto)") do |port|
115
- @port = port
116
- end
117
-
118
- parser.on("--read-timeout=TIMEOUT", Integer,
119
- "Timeout on reading response from Groonga server.",
120
- "You can disable timeout by specifying -1.",
121
- "(#{@read_timeout})") do |timeout|
122
- @read_timeout = timeout
123
- end
76
+ parser.separator("Request:")
124
77
 
125
78
  parser.on("--split-load-chunk-size=SIZE", Integer,
126
79
  "Split a large load to small loads.",
@@ -142,21 +95,6 @@ module Groonga
142
95
  "(#{@chunk})") do |boolean|
143
96
  @chunk = boolean
144
97
  end
145
-
146
- command_file_paths = parser.parse(argv)
147
-
148
- @port ||= default_port(@protocol)
149
-
150
- command_file_paths
151
- end
152
-
153
- def default_port(protocol)
154
- case protocol
155
- when :http
156
- 10041
157
- when :gqtp
158
- 10043
159
- end
160
98
  end
161
99
 
162
100
  class Runner
@@ -0,0 +1,111 @@
1
+ # Copyright (C) 2015-2017 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 "optparse"
18
+
19
+ require "groonga/client"
20
+
21
+ module Groonga
22
+ class Client
23
+ module CommandLine
24
+ class Parser
25
+ def initialize(options={})
26
+ @url = nil
27
+ @protocol = :http
28
+ @host = "localhost"
29
+ @port = nil
30
+
31
+ @read_timeout = options[:read_timeout] || Client::Default::READ_TIMEOUT
32
+ end
33
+
34
+ def parse(arguments)
35
+ parser = OptionParser.new
36
+ parser.version = VERSION
37
+
38
+ parser.separator("")
39
+
40
+ parser.separator("Connection:")
41
+
42
+ parser.on("--url=URL",
43
+ "URL to connect to Groonga server.",
44
+ "If this option is specified,",
45
+ "--protocol, --host and --port are ignored.") do |url|
46
+ @url = url
47
+ end
48
+
49
+ available_protocols = [:http, :gqtp]
50
+ parser.on("--protocol=PROTOCOL", [:http, :gqtp],
51
+ "Protocol to connect to Groonga server.",
52
+ "[#{available_protocols.join(", ")}]",
53
+ "(#{@protocol})") do |protocol|
54
+ @protocol = protocol
55
+ end
56
+
57
+ parser.on("--host=HOST",
58
+ "Groonga server to be connected.",
59
+ "(#{@host})") do |host|
60
+ @host = host
61
+ end
62
+
63
+ parser.on("--port=PORT", Integer,
64
+ "Port number of Groonga server to be connected.",
65
+ "(auto)") do |port|
66
+ @port = port
67
+ end
68
+
69
+ parser.on("--read-timeout=TIMEOUT", Integer,
70
+ "Timeout on reading response from Groonga server.",
71
+ "You can disable timeout by specifying -1.",
72
+ "(#{@read_timeout})") do |timeout|
73
+ @read_timeout = timeout
74
+ end
75
+
76
+ yield(parser)
77
+
78
+ rest = parser.parse(arguments)
79
+
80
+ @port ||= default_port(@protocol)
81
+
82
+ rest
83
+ end
84
+
85
+ def open_client(options={})
86
+ default_options = {
87
+ :url => @url,
88
+ :protocol => @protocol,
89
+ :host => @host,
90
+ :port => @port,
91
+ :read_timeout => @read_timeout,
92
+ :backend => :synchronous,
93
+ }
94
+ Client.open(default_options.merge(options)) do |client|
95
+ yield(client)
96
+ end
97
+ end
98
+
99
+ private
100
+ def default_port(protocol)
101
+ case protocol
102
+ when :http
103
+ 10041
104
+ when :gqtp
105
+ 10043
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,122 @@
1
+ # Copyright (C) 2017 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
+ module Groonga
18
+ class Client
19
+ module CommandLine
20
+ class Runner
21
+ def initialize(client)
22
+ @client = client
23
+ end
24
+
25
+ def run(&block)
26
+ catch do |tag|
27
+ @abort_tag = tag
28
+ run_internal(&block)
29
+ end
30
+ end
31
+
32
+ private
33
+ def abort_run(message)
34
+ $stderr.puts(message)
35
+ throw(@abort_tag, false)
36
+ end
37
+
38
+ def execute_command(name, arguments={})
39
+ response = @client.execute(name, arguments)
40
+ unless response.success?
41
+ abort_run("Failed to run #{name}: #{response.inspect}")
42
+ end
43
+ response
44
+ end
45
+
46
+ def config_get(key)
47
+ execute_command(:config_get, :key => key).body
48
+ end
49
+
50
+ def config_set(key, value)
51
+ execute_command(:config_set, :key => key, :value => value).body
52
+ end
53
+
54
+ def object_exist?(name)
55
+ execute_command(:object_exist, :name => name).body
56
+ end
57
+
58
+ def table_list
59
+ execute_command(:table_list)
60
+ end
61
+
62
+ def column_list(table)
63
+ execute_command(:column_list, :table => table)
64
+ end
65
+
66
+ def column_create(table_name, name, flags, type, source)
67
+ execute_command(:column_create,
68
+ :table => table_name,
69
+ :name => name,
70
+ :flags => flags,
71
+ :type => type,
72
+ :source => source).body
73
+ end
74
+
75
+ def column_create_similar(table_name, column_name, base_column_name)
76
+ if object_exist?(:schema)
77
+ info = execute_command(:schema)["#{table_name}.#{base_column_name}"]
78
+ arguments = info.command.arguments.merge("name" => column_name)
79
+ execute_command(:column_create, arguments).body
80
+ else
81
+ base_column = column_list(table_name).find do |column|
82
+ column.name == base_column_name
83
+ end
84
+ range = base_column.range
85
+ source_columns = base_column.sources.collect do |source|
86
+ if source.include?(".")
87
+ source.split(".", 2)[1]
88
+ else
89
+ "_key"
90
+ end
91
+ end
92
+ flags = base_column.flags.dup
93
+ flags.delete("PERSISTENT")
94
+ column_create(table_name,
95
+ column_name,
96
+ flags.join("|"),
97
+ range,
98
+ source_columns.join(","))
99
+ end
100
+ end
101
+
102
+ def column_remove(table, column)
103
+ execute_command(:column_remove,
104
+ :table => table,
105
+ :name => column).body
106
+ end
107
+
108
+ def column_rename(table, name, new_name)
109
+ execute_command(:column_rename,
110
+ :table => table,
111
+ :name => name,
112
+ :new_name => new_name).body
113
+ end
114
+
115
+ def select(table, arguments={})
116
+ execute_command(:select,
117
+ arguments.merge(:table => table))
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -27,6 +27,27 @@ module Groonga
27
27
  module Protocol
28
28
  class HTTP
29
29
  class Synchronous
30
+ # TODO: Workaround to disable retry in net/http.
31
+ class HTTPClient < Net::HTTP
32
+ class ReadTimeout < StandardError
33
+ end
34
+
35
+ module ReadTimeoutConvertable
36
+ def rbuf_fill
37
+ begin
38
+ super
39
+ rescue Net::ReadTimeout => error
40
+ raise ReadTimeout, error.message, error.backtrace
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+ def on_connect
47
+ @socket.extend(ReadTimeoutConvertable)
48
+ end
49
+ end
50
+
30
51
  include PathResolvable
31
52
 
32
53
  def initialize(url, options={})
@@ -36,7 +57,7 @@ module Groonga
36
57
 
37
58
  def send(command)
38
59
  begin
39
- Net::HTTP.start(@url.host, @url.port, start_options) do |http|
60
+ HTTPClient.start(@url.host, @url.port, start_options) do |http|
40
61
  http.read_timeout = read_timeout
41
62
  response = send_request(http, command)
42
63
  case response
@@ -64,6 +64,14 @@ module Groonga
64
64
  :domain,
65
65
  :range,
66
66
  :source)
67
+ # @return [String]
68
+ # The column name with table name such as `TABLE.COLUMN`.
69
+ #
70
+ # @since 0.5.4
71
+ def full_name
72
+ "#{domain}.#{name}"
73
+ end
74
+
67
75
  # @return [::Array<String>]
68
76
  # The flag names of the column.
69
77
  #
@@ -95,6 +103,8 @@ module Groonga
95
103
  def index?
96
104
  flags.include?("COLUMN_INDEX")
97
105
  end
106
+
107
+ alias_method :sources, :source
98
108
  end
99
109
  end
100
110
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Groonga
18
18
  class Client
19
- VERSION = "0.5.4"
19
+ VERSION = "0.5.5"
20
20
  end
21
21
  end
@@ -0,0 +1,87 @@
1
+ # Copyright (C) 2017 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 "groonga/command/parser"
18
+
19
+ require "groonga/client"
20
+ require "groonga/client/test-helper"
21
+
22
+ module CommandLineTestHelper
23
+ def groonga_url
24
+ @groonga_server_runner.url.to_s
25
+ end
26
+
27
+ def open_client
28
+ Groonga::Client.open(:url => groonga_url) do |client|
29
+ yield(client)
30
+ end
31
+ end
32
+
33
+ def restore(commands)
34
+ open_client do |client|
35
+ values = nil
36
+ Groonga::Command::Parser.parse(commands) do |event, *args|
37
+ case event
38
+ when :on_command
39
+ command, = args
40
+ response = client.execute(command)
41
+ unless response.success?
42
+ raise Groonga::Client::Request::ErrorResponse.new(response)
43
+ end
44
+ when :on_load_start
45
+ command, = args
46
+ values = []
47
+ when :on_load_columns
48
+ command, columns = args
49
+ command[:columns] ||= columns.join(",")
50
+ when :on_load_value
51
+ command, value = args
52
+ values << value
53
+ when :on_load_complete
54
+ command, = args
55
+ command[:values] ||= JSON.generate(values)
56
+ response = client.execute(command)
57
+ unless response.success?
58
+ raise Groonga::Client::Request::ErrorResponse.new(response)
59
+ end
60
+ else
61
+ p [:unhandled_event, event, *args]
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def dump
68
+ open_client do |client|
69
+ client.dump.body
70
+ end
71
+ end
72
+
73
+ def capture_outputs
74
+ begin
75
+ stdout, $stdout = $stdout, StringIO.new
76
+ stderr, $stderr = $stderr, StringIO.new
77
+ result = yield
78
+ [
79
+ result,
80
+ $stdout.string,
81
+ $stderr.string,
82
+ ]
83
+ ensure
84
+ $stdout, $stderr = stdout, stderr
85
+ end
86
+ end
87
+ end