rroonga 9.0.2 → 10.0.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/Rakefile +9 -142
  4. data/doc/text/news.md +73 -1
  5. data/doc/text/tutorial.md +1 -1
  6. data/ext/groonga/extconf.rb +9 -74
  7. data/ext/groonga/rb-grn-context.c +27 -0
  8. data/ext/groonga/rb-grn-expression-builder.c +3 -3
  9. data/ext/groonga/rb-grn-flushable.c +7 -0
  10. data/ext/groonga/rb-grn-index-column.c +28 -0
  11. data/ext/groonga/rb-grn-index-cursor.c +19 -0
  12. data/ext/groonga/rb-grn-logger.c +17 -3
  13. data/ext/groonga/rb-grn-object.c +236 -22
  14. data/ext/groonga/rb-grn-table-key-support.c +26 -7
  15. data/ext/groonga/rb-grn-table.c +119 -87
  16. data/ext/groonga/rb-grn-type.c +5 -1
  17. data/ext/groonga/rb-grn-utils.c +17 -1
  18. data/ext/groonga/rb-grn.h +7 -13
  19. data/ext/groonga/rb-groonga.c +2 -2
  20. data/lib/groonga.rb +3 -7
  21. data/lib/groonga/dumper.rb +3 -0
  22. data/lib/groonga/record.rb +2 -2
  23. data/rroonga.gemspec +4 -5
  24. data/test/groonga-test-utils.rb +34 -5
  25. data/test/run-test.rb +1 -3
  26. data/test/test-accessor.rb +63 -7
  27. data/test/test-column.rb +12 -1
  28. data/test/test-context.rb +25 -0
  29. data/test/test-exception.rb +5 -0
  30. data/test/test-flushable.rb +51 -6
  31. data/test/test-index-column.rb +67 -6
  32. data/test/test-index-cursor.rb +26 -0
  33. data/test/test-logger.rb +56 -11
  34. data/test/test-plugin.rb +1 -0
  35. data/test/test-query-logger.rb +4 -3
  36. data/test/test-record.rb +2 -1
  37. data/test/test-remote.rb +56 -10
  38. data/test/test-schema-dumper.rb +13 -0
  39. data/test/test-schema.rb +9 -1
  40. data/test/test-table-arrow.rb +1 -1
  41. data/test/test-table.rb +21 -1
  42. data/test/test-variable.rb +23 -7
  43. metadata +65 -106
@@ -108,11 +108,16 @@ class TooManyOpenFilesTest < Test::Unit::TestCase
108
108
  include GroongaTestUtils
109
109
 
110
110
  def setup
111
+ @sub_context = nil
112
+ unless Process.const_defined?(:RLIMIT_NOFILE)
113
+ omit("No Process::RLIMIT_NOFILE")
114
+ end
111
115
  setup_database
112
116
  @sub_context = create_sub_context
113
117
  end
114
118
 
115
119
  def teardown
120
+ return if @sub_context.nil?
116
121
  @sub_context.database.close
117
122
  @sub_context.close
118
123
  end
@@ -18,32 +18,77 @@ class FlushableTest < Test::Unit::TestCase
18
18
 
19
19
  setup :setup_database
20
20
 
21
+ def normalize_query_log(log)
22
+ log.lines.collect do |line|
23
+ line.chomp.gsub(/\A.*?:\d+ /, "")
24
+ end
25
+ end
26
+
21
27
  def test_flush_table
22
28
  table = Groonga::Hash.create
23
- assert_nothing_raised do
29
+ log = collect_query_log do
24
30
  table.flush
25
31
  end
32
+ assert_equal([
33
+ "flush[(anonymous:table:hash_key)]",
34
+ ],
35
+ normalize_query_log(log))
26
36
  end
27
37
 
28
38
  def test_flush_column
29
39
  table = Groonga::Hash.create(:name => "Users")
30
40
  column = table.define_column("name", "ShortText")
31
- assert_nothing_raised do
41
+ log = collect_query_log do
32
42
  column.flush
33
43
  end
44
+ assert_equal([
45
+ "flush[Users.name]",
46
+ ],
47
+ normalize_query_log(log))
34
48
  end
35
49
 
36
50
  def test_flush_database
37
- assert_nothing_raised do
51
+ table = Groonga::Hash.create(:name => "Users")
52
+ table.define_column("name", "ShortText")
53
+ log = collect_query_log do
38
54
  @database.flush
39
55
  end
56
+ assert_equal([
57
+ "flush[Users.name]",
58
+ "flush[Users]",
59
+ "flush[(anonymous:table:dat_key)]",
60
+ "flush[(anonymous:column:var_size)]",
61
+ "flush[(anonymous:table:hash_key)]",
62
+ "flush[(anonymous:column:var_size)]",
63
+ "flush[(DB)]",
64
+ ],
65
+ normalize_query_log(log))
40
66
  end
41
67
 
42
68
  def test_flush_not_recursive
43
- table = Groonga::Hash.create
44
- table.extend(Groonga::Flushable)
45
- assert_nothing_raised do
69
+ table = Groonga::Hash.create(:name => "Users")
70
+ table.define_column("name", "ShortText")
71
+ log = collect_query_log do
46
72
  table.flush(:recursive => false)
47
73
  end
74
+ assert_equal([
75
+ "flush[Users]",
76
+ ],
77
+ normalize_query_log(log))
78
+ end
79
+
80
+ def test_flush_dependent
81
+ referenced_table = Groonga::Hash.create(name: "Names")
82
+ table = Groonga::Hash.create(:name => "Users")
83
+ table.define_column("name", referenced_table)
84
+ log = collect_query_log do
85
+ table.flush(:recursive => false, :dependent => true)
86
+ end
87
+ assert_equal([
88
+ "flush[Names]",
89
+ "flush[Users.name]",
90
+ "flush[Users]",
91
+ ],
92
+ normalize_query_log(log))
48
93
  end
49
94
  end
@@ -33,11 +33,11 @@ class IndexColumnTest < Test::Unit::TestCase
33
33
  articles = Groonga::Array.create(:name => "Articles")
34
34
  articles.define_column("content", "Text")
35
35
 
36
- terms = Groonga::Hash.create(:name => "Terms",
37
- :key_type => "ShortText",
38
- :default_tokenizer => "TokenBigram")
39
- @index = terms.define_index_column("content", articles,
40
- :with_section => true)
36
+ @terms = Groonga::Hash.create(:name => "Terms",
37
+ :key_type => "ShortText",
38
+ :default_tokenizer => "TokenBigram")
39
+ @index = @terms.define_index_column("content", articles,
40
+ :with_section => true)
41
41
  end
42
42
 
43
43
  def test_index?
@@ -63,6 +63,20 @@ class IndexColumnTest < Test::Unit::TestCase
63
63
  not @index.data?
64
64
  end
65
65
  end
66
+
67
+ sub_test_case("#lexicon?") do
68
+ def test_true
69
+ assert do
70
+ @terms.lexicon?
71
+ end
72
+ end
73
+
74
+ def test_false
75
+ assert do
76
+ not @index.lexicon?
77
+ end
78
+ end
79
+ end
66
80
  end
67
81
 
68
82
  class CRUDTest < self
@@ -438,11 +452,35 @@ class IndexColumnTest < Test::Unit::TestCase
438
452
  ])
439
453
  end
440
454
 
455
+ def test_large
456
+ Groonga::Schema.define do |schema|
457
+ schema.create_table("Tags",
458
+ :type => :patricia_trie,
459
+ :key_type => "ShortText") do |table|
460
+ table.index("Articles.tags",
461
+ :name => "large",
462
+ :size => :large)
463
+ table.index("Articles.tags",
464
+ :name => "default")
465
+ end
466
+ end
467
+
468
+ assert_equal([
469
+ true,
470
+ false,
471
+ ],
472
+ [
473
+ context["Tags.large"].large?,
474
+ context["Tags.default"].large?,
475
+ ])
476
+ end
477
+
441
478
  def test_invalid
442
479
  Groonga::Schema.create_table("Tags",
443
480
  :type => :patricia_trie,
444
481
  :key_type => "ShortText")
445
- message = ":size must be nil, :small or :medium: <invalid>"
482
+ message =
483
+ ":size must be nil, :small, :medium or :large: <invalid>"
446
484
  assert_raise(ArgumentError.new(message)) do
447
485
  tags = context["Tags"]
448
486
  tags.define_index_column("small",
@@ -818,5 +856,28 @@ class IndexColumnTest < Test::Unit::TestCase
818
856
  ">",
819
857
  index.inspect)
820
858
  end
859
+
860
+ def test_large_size
861
+ Groonga::Schema.define do |schema|
862
+ schema.create_table("Tags",
863
+ :type => :hash,
864
+ :key_type => "ShortText") do |tags|
865
+ tags.index("Articles.tag", :size => :large)
866
+ end
867
+ end
868
+
869
+ index = context["Tags.Articles_tag"]
870
+ source_column_names = index.sources.collect(&:local_name).join(",")
871
+ assert_equal("\#<Groonga::IndexColumn " +
872
+ "id: <#{index.id}>, " +
873
+ "name: <#{index.name}>, " +
874
+ "path: <#{index.path}>, " +
875
+ "domain: <#{index.domain.name}>, " +
876
+ "range: <#{index.range.name}>, " +
877
+ "flags: <LARGE>, " +
878
+ "sources: <#{source_column_names}>" +
879
+ ">",
880
+ index.inspect)
881
+ end
821
882
  end
822
883
  end
@@ -1,4 +1,5 @@
1
1
  # Copyright (C) 2012-2017 Kouhei Sutou <kou@clear-code.com>
2
+ # Copyright (C) 2019 Horimoto Yasuhiro <horimoto@clear-code.com>
2
3
  #
3
4
  # This library is free software; you can redistribute it and/or
4
5
  # modify it under the terms of the GNU Lesser General Public
@@ -155,6 +156,31 @@ class IndexCursorTest < Test::Unit::TestCase
155
156
  assert_equal("l", term.key)
156
157
  end
157
158
 
159
+ sub_test_case(".set_min?") do
160
+ def setup
161
+ default_set_min = Groonga::IndexCursor.set_min?
162
+ begin
163
+ yield
164
+ ensure
165
+ Groonga::IndexCursor.set_min = default_set_min
166
+ end
167
+ end
168
+
169
+ def test_true
170
+ Groonga::IndexCursor.set_min = true
171
+ assert do
172
+ Groonga::IndexCursor.set_min?
173
+ end
174
+ end
175
+
176
+ def test_false
177
+ Groonga::IndexCursor.set_min = false
178
+ assert do
179
+ not Groonga::IndexCursor.set_min?
180
+ end
181
+ end
182
+ end
183
+
158
184
  private
159
185
  def create_hashes(keys, values)
160
186
  hashes = []
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2010-2018 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2010-2019 Kouhei Sutou <kou@clear-code.com>
2
2
  # Copyright (C) 2016 Masafumi Yokoyama <yokoyama@clear-code.com>
3
3
  #
4
4
  # This library is free software; you can redistribute it and/or
@@ -21,15 +21,18 @@ class LoggerTest < Test::Unit::TestCase
21
21
  @default_log_path = Groonga::Logger.path
22
22
  @default_log_max_level = Groonga::Logger.max_level
23
23
  @default_rotate_threshold_size = Groonga::Logger.rotate_threshold_size
24
+ @default_flags = Groonga::Logger.flags
24
25
  end
25
26
 
26
27
  def teardown
27
28
  Groonga::Logger.path = @default_log_path
28
29
  Groonga::Logger.max_level = @default_log_max_level
29
30
  Groonga::Logger.rotate_threshold_size = @default_rotate_threshold_size
31
+ Groonga::Logger.flags = @default_flags
30
32
  end
31
33
 
32
34
  def test_reopen
35
+ only_not_windows
33
36
  Groonga::Logger.unregister
34
37
  Groonga::Logger.path = @log_path.to_s
35
38
  if @log_path.exist?
@@ -46,12 +49,22 @@ class LoggerTest < Test::Unit::TestCase
46
49
  assert_equal(:debug, Groonga::Logger.max_level)
47
50
  end
48
51
 
49
- def test_flags
50
- default_flags = Groonga::Logger::Flags::TIME |
51
- Groonga::Logger::Flags::MESSAGE
52
- assert_equal(default_flags, Groonga::Logger.flags)
53
- Groonga::Logger.flags = Groonga::Logger::Flags::LOCATION
54
- assert_equal(Groonga::Logger::Flags::LOCATION, Groonga::Logger.flags)
52
+ sub_test_case ".flags" do
53
+ def test_default
54
+ assert_equal(Groonga::Logger::Flags::TIME |
55
+ Groonga::Logger::Flags::MESSAGE,
56
+ Groonga::Logger.flags)
57
+ end
58
+
59
+ def test_location
60
+ Groonga::Logger.flags = Groonga::Logger::Flags::LOCATION
61
+ assert_equal(Groonga::Logger::Flags::LOCATION, Groonga::Logger.flags)
62
+ end
63
+
64
+ def test_thread_id
65
+ Groonga::Logger.flags = Groonga::Logger::Flags::THREAD_ID
66
+ assert_equal(Groonga::Logger::Flags::THREAD_ID, Groonga::Logger.flags)
67
+ end
55
68
  end
56
69
 
57
70
  sub_test_case ".log" do
@@ -89,7 +102,8 @@ class LoggerTest < Test::Unit::TestCase
89
102
 
90
103
  test "default location" do
91
104
  locations = []
92
- Groonga::Logger.register do |event, level, time, title, message, location|
105
+ Groonga::Logger.register(thread_id: false) do |*args|
106
+ location = args[5]
93
107
  locations << location
94
108
  end
95
109
  Groonga::Logger.log("message"); line = __LINE__
@@ -102,7 +116,8 @@ class LoggerTest < Test::Unit::TestCase
102
116
 
103
117
  test ":file" do
104
118
  locations = []
105
- Groonga::Logger.register do |event, level, time, title, message, location|
119
+ Groonga::Logger.register(thread_id: false) do |*args|
120
+ location = args[5]
106
121
  locations << location
107
122
  end
108
123
  Groonga::Logger.log("message", :file => "file.rb")
@@ -118,7 +133,8 @@ class LoggerTest < Test::Unit::TestCase
118
133
 
119
134
  test ":line" do
120
135
  locations = []
121
- Groonga::Logger.register do |event, level, time, title, message, location|
136
+ Groonga::Logger.register(thread_id: false) do |*args|
137
+ location = args[5]
122
138
  locations << location
123
139
  end
124
140
  Groonga::Logger.log("message", :line => 100)
@@ -134,7 +150,8 @@ class LoggerTest < Test::Unit::TestCase
134
150
 
135
151
  test ":function" do
136
152
  locations = []
137
- Groonga::Logger.register do |event, level, time, title, message, location|
153
+ Groonga::Logger.register(thread_id: false) do |*args|
154
+ location = args[5]
138
155
  locations << location
139
156
  end
140
157
  Groonga::Logger.log("message", :function => "method_name")
@@ -149,6 +166,34 @@ class LoggerTest < Test::Unit::TestCase
149
166
  end
150
167
  end
151
168
 
169
+ sub_test_case ".register" do
170
+ setup do
171
+ GC.disable
172
+ end
173
+
174
+ teardown do
175
+ Groonga::Logger.unregister
176
+ GC.enable
177
+ end
178
+
179
+ test ":thread_id" do
180
+ locations = []
181
+ Groonga::Logger.register(location: false,
182
+ thread_id: true) do |*args|
183
+ location = args[5]
184
+ locations << location
185
+ end
186
+ Groonga::Logger.log("message")
187
+ locations = locations.collect do |location|
188
+ location.gsub(/\A([a-f\d]+)\z/, "THREAD_ID")
189
+ end
190
+ assert_equal([
191
+ "THREAD_ID",
192
+ ],
193
+ locations)
194
+ end
195
+ end
196
+
152
197
  def test_rotate_threshold_size
153
198
  Groonga::Logger.unregister
154
199
  Groonga::Logger.path = @log_path.to_s
@@ -48,6 +48,7 @@ class PluginTest < Test::Unit::TestCase
48
48
  end
49
49
 
50
50
  def test_by_path
51
+ only_not_windows # TODO: We can remove this with Groonga 9.0.3
51
52
  context.register_plugin("token_filters/stop_word")
52
53
  assert_not_nil(context["TokenFilterStopWord"])
53
54
  plugin_path = "#{Groonga::Plugin.system_plugins_dir}/"
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2018 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2015-2019 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
@@ -29,6 +29,7 @@ class QueryLoggerTest < Test::Unit::TestCase
29
29
  end
30
30
 
31
31
  def test_reopen
32
+ only_not_windows
32
33
  Groonga::QueryLogger.unregister
33
34
  Groonga::QueryLogger.path = @query_log_path.to_s
34
35
  if @query_log_path.exist?
@@ -109,7 +110,7 @@ class QueryLoggerTest < Test::Unit::TestCase
109
110
  Groonga::QueryLogger.log("default")
110
111
  Groonga::QueryLogger.log("flags", :flags => "command")
111
112
  normalized_infos = infos.collect do |info|
112
- info = info.gsub(/\A0x[a-f\d]+\|/,
113
+ info = info.gsub(/\A[a-zA-Z\d]+\|/,
113
114
  "context_id|")
114
115
  info.gsub(/\|[\d]+ \z/,
115
116
  "|timestamp ")
@@ -129,7 +130,7 @@ class QueryLoggerTest < Test::Unit::TestCase
129
130
  Groonga::QueryLogger.log("default")
130
131
  Groonga::QueryLogger.log("mark", :mark => ":")
131
132
  normalized_infos = infos.collect do |info|
132
- info.gsub(/\A0x[a-f\d]+\|([^\d])?[\d]+ \z/,
133
+ info.gsub(/\A[a-zA-Z\d]+\|([^\d])?[\d]+ \z/,
133
134
  "context_id|\\1timestamp ")
134
135
  end
135
136
  assert_equal([
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2013 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2009-2019 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
@@ -647,6 +647,7 @@ class RecordTest < Test::Unit::TestCase
647
647
  end
648
648
 
649
649
  def test_to_json
650
+ only_not_windows
650
651
  ENV["TZ"] = "Japan"
651
652
  created_at = Time.parse("2013-05-16T16:57:34+09:00")
652
653
  values = {
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2009-2019 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,24 +20,69 @@ class RemoteTest < Test::Unit::TestCase
20
20
  def setup_remote_connection
21
21
  @process_id = nil
22
22
 
23
- package_config = PKGConfig.package_config("groonga")
24
- groonga = package_config.variable("groonga")
23
+ vendor_local_bin = File.join(__dir__, "..", "vendor", "local", "bin")
24
+ if File.exist?(vendor_local_bin)
25
+ groonga = File.join(vendor_local_bin, "groonga")
26
+ else
27
+ package_config = PKGConfig.package_config("groonga")
28
+ groonga = package_config.variable("groonga")
29
+ groonga = normalize_groonga_path(groonga)
30
+ groonga = "groonga" unless File.exist?(groonga)
31
+ end
25
32
 
26
33
  @host = "127.0.0.1"
27
34
  @port = 12345
28
35
  @remote_database_path = @tmp_dir + "remote-database"
29
- @process_id = Process.fork do
30
- exec(groonga,
31
- "-i", @host,
32
- "-p", @port.to_s,
33
- "-s", "-n", @remote_database_path.to_s)
36
+ @process_id = spawn(groonga,
37
+ "-i", @host,
38
+ "-p", @port.to_s,
39
+ "-s",
40
+ "-n", @remote_database_path.to_s)
41
+ Timeout.timeout(5) do
42
+ loop do
43
+ begin
44
+ open_client do |client|
45
+ client.status
46
+ end
47
+ rescue Groonga::Client::Error
48
+ else
49
+ break
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def normalize_groonga_path(groonga)
56
+ return groonga unless groonga
57
+ return groonga unless Object.const_defined?(:RubyInstaller)
58
+
59
+ msys2_installation = RubyInstaller::Runtime.msys2_installation
60
+ mingw_prefix = msys2_installation.mingw_prefix
61
+ mingw_bin_path = "#{mingw_prefix}/bin/"
62
+ mingw_bin_path_windows = "#{msys2_installation.mingw_bin_path}\\"
63
+ groonga.gsub(/\A#{Regexp.escape(mingw_bin_path)}/) do
64
+ mingw_bin_path_windows
34
65
  end
35
- sleep(1)
36
66
  end
37
67
 
38
68
  teardown
39
69
  def teardown_remote_connection
40
- Process.kill(:TERM, @process_id) if @process_id
70
+ if @process_id
71
+ begin
72
+ open_client do |client|
73
+ client.shutdown
74
+ end
75
+ rescue Groonga::Client::Error
76
+ end
77
+ Process.waitpid(@process_id)
78
+ end
79
+ end
80
+
81
+ def open_client(&block)
82
+ Groonga::Client.open(host: @host,
83
+ port: @port,
84
+ protocol: :gqtp,
85
+ &block)
41
86
  end
42
87
 
43
88
  def test_send
@@ -53,6 +98,7 @@ class RemoteTest < Test::Unit::TestCase
53
98
  "command_version",
54
99
  "default_command_version",
55
100
  "max_command_version",
101
+ "n_jobs",
56
102
  "n_queries",
57
103
  "start_time",
58
104
  "starttime",