rroonga 2.0.4 → 2.0.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.
Files changed (90) hide show
  1. data/Rakefile +21 -2
  2. data/bin/grndump +3 -2
  3. data/ext/groonga/extconf.rb +1 -6
  4. data/ext/groonga/rb-grn-array.c +58 -31
  5. data/ext/groonga/rb-grn-column.c +220 -148
  6. data/ext/groonga/rb-grn-context.c +46 -32
  7. data/ext/groonga/rb-grn-database.c +102 -90
  8. data/ext/groonga/rb-grn-double-array-trie.c +205 -163
  9. data/ext/groonga/rb-grn-encoding-support.c +2 -3
  10. data/ext/groonga/rb-grn-encoding.c +13 -8
  11. data/ext/groonga/rb-grn-exception.c +1 -1
  12. data/ext/groonga/rb-grn-expression.c +110 -133
  13. data/ext/groonga/rb-grn-fix-size-column.c +5 -4
  14. data/ext/groonga/rb-grn-geo-point.c +55 -0
  15. data/ext/groonga/rb-grn-hash.c +120 -82
  16. data/ext/groonga/rb-grn-index-column.c +66 -70
  17. data/ext/groonga/rb-grn-index-cursor.c +3 -0
  18. data/ext/groonga/rb-grn-logger.c +33 -51
  19. data/ext/groonga/rb-grn-object.c +2 -0
  20. data/ext/groonga/rb-grn-operator.c +1 -1
  21. data/ext/groonga/rb-grn-patricia-trie.c +287 -232
  22. data/ext/groonga/rb-grn-plugin.c +11 -14
  23. data/ext/groonga/rb-grn-snippet.c +37 -54
  24. data/ext/groonga/rb-grn-table-cursor-key-support.c +3 -3
  25. data/ext/groonga/rb-grn-table-cursor.c +8 -6
  26. data/ext/groonga/rb-grn-table-key-support.c +22 -29
  27. data/ext/groonga/rb-grn-table.c +355 -279
  28. data/ext/groonga/rb-grn-type.c +18 -25
  29. data/ext/groonga/rb-grn-utils.c +77 -7
  30. data/ext/groonga/rb-grn-variable-size-column.c +12 -20
  31. data/ext/groonga/rb-grn-view.c +56 -51
  32. data/ext/groonga/rb-grn.h +28 -1
  33. data/ext/groonga/rb-groonga.c +1 -0
  34. data/lib/groonga.rb +2 -0
  35. data/lib/groonga/command.rb +3 -1
  36. data/lib/groonga/database.rb +27 -0
  37. data/lib/groonga/dumper.rb +96 -17
  38. data/lib/groonga/geo-point.rb +216 -0
  39. data/lib/groonga/schema.rb +29 -46
  40. data/rroonga-build.rb +1 -1
  41. data/rroonga.gemspec +90 -0
  42. data/test/groonga-test-utils.rb +168 -0
  43. data/test/run-test.rb +60 -0
  44. data/test/test-accessor.rb +36 -0
  45. data/test/test-array.rb +146 -0
  46. data/test/test-column.rb +350 -0
  47. data/test/test-command-select.rb +181 -0
  48. data/test/test-context.rb +130 -0
  49. data/test/test-database-dumper.rb +259 -0
  50. data/test/test-database.rb +173 -0
  51. data/test/test-double-array-trie.rb +189 -0
  52. data/test/test-encoding.rb +33 -0
  53. data/test/test-exception.rb +230 -0
  54. data/test/test-expression-builder.rb +602 -0
  55. data/test/test-expression.rb +134 -0
  56. data/test/test-fix-size-column.rb +77 -0
  57. data/test/test-geo-point.rb +190 -0
  58. data/test/test-gqtp.rb +70 -0
  59. data/test/test-hash.rb +367 -0
  60. data/test/test-index-column.rb +180 -0
  61. data/test/test-index-cursor.rb +123 -0
  62. data/test/test-logger.rb +37 -0
  63. data/test/test-pagination.rb +249 -0
  64. data/test/test-patricia-trie.rb +440 -0
  65. data/test/test-plugin.rb +35 -0
  66. data/test/test-procedure.rb +37 -0
  67. data/test/test-query-log.rb +258 -0
  68. data/test/test-record.rb +577 -0
  69. data/test/test-remote.rb +63 -0
  70. data/test/test-schema-create-table.rb +267 -0
  71. data/test/test-schema-dumper.rb +235 -0
  72. data/test/test-schema-type.rb +208 -0
  73. data/test/test-schema-view.rb +90 -0
  74. data/test/test-schema.rb +886 -0
  75. data/test/test-snippet.rb +130 -0
  76. data/test/test-table-dumper.rb +353 -0
  77. data/test/test-table-offset-and-limit.rb +100 -0
  78. data/test/test-table-select-mecab.rb +80 -0
  79. data/test/test-table-select-normalize.rb +57 -0
  80. data/test/test-table-select-weight.rb +123 -0
  81. data/test/test-table-select.rb +191 -0
  82. data/test/test-table-traverse.rb +304 -0
  83. data/test/test-table.rb +711 -0
  84. data/test/test-type.rb +79 -0
  85. data/test/test-variable-size-column.rb +147 -0
  86. data/test/test-variable.rb +28 -0
  87. data/test/test-vector-column.rb +76 -0
  88. data/test/test-version.rb +61 -0
  89. data/test/test-view.rb +72 -0
  90. metadata +330 -202
@@ -0,0 +1,304 @@
1
+ # Copyright (C) 2009-2010 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 version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ class TableTraverseTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ def setup
20
+ setup_database
21
+
22
+ @bookmarks_path = @tables_dir + "table"
23
+ @bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks",
24
+ :path => @bookmarks_path.to_s)
25
+ @groonga_bookmark = @bookmarks.add("groonga")
26
+ @cutter_bookmark = @bookmarks.add("Cutter")
27
+ @ruby_bookmark = @bookmarks.add("Ruby")
28
+ end
29
+
30
+ class CursorTest < self
31
+ def test_default
32
+ keys = []
33
+ @bookmarks.open_cursor do |cursor|
34
+ while cursor.next
35
+ keys << cursor.key
36
+ end
37
+ end
38
+ assert_equal(["Cutter", "Ruby", "groonga"],
39
+ keys)
40
+ end
41
+
42
+ def test_order_ascending
43
+ record_and_key_list = []
44
+ @bookmarks.open_cursor(:order => :ascending) do |cursor|
45
+ record_and_key_list = cursor.collect {|record| [record, cursor.key]}
46
+ end
47
+ assert_equal([[@cutter_bookmark, "Cutter"],
48
+ [@ruby_bookmark, "Ruby"],
49
+ [@groonga_bookmark, "groonga"]],
50
+ record_and_key_list)
51
+ end
52
+
53
+ def test_without_limit_and_offset
54
+ users = create_users
55
+ add_users(users)
56
+ results = []
57
+ users.open_cursor do |cursor|
58
+ cursor.each do |record|
59
+ results << record["name"]
60
+ end
61
+ end
62
+
63
+ assert_equal((100..199).collect {|i| "user#{i}"},
64
+ results)
65
+ end
66
+
67
+ def test_with_limit
68
+ users = create_users
69
+ add_users(users)
70
+ results = []
71
+ users.open_cursor(:limit => 20) do |cursor|
72
+ cursor.each do |record|
73
+ results << record["name"]
74
+ end
75
+ end
76
+
77
+ assert_equal((100...120).collect {|i| "user#{i}"},
78
+ results)
79
+ end
80
+
81
+ def test_with_offset
82
+ users = create_users
83
+ add_users(users)
84
+ results = []
85
+ users.open_cursor(:offset => 20) do |cursor|
86
+ cursor.each do |record|
87
+ results << record["name"]
88
+ end
89
+ end
90
+
91
+ assert_equal((120...200).collect {|i| "user#{i}"},
92
+ results)
93
+ end
94
+
95
+ def test_with_limit_and_offset
96
+ users = create_users
97
+ add_users(users)
98
+ results = []
99
+ users.open_cursor(:limit => 20, :offset => 20) do |cursor|
100
+ cursor.each do |record|
101
+ results << record["name"]
102
+ end
103
+ end
104
+
105
+ assert_equal((120...140).collect {|i| "user#{i}"},
106
+ results)
107
+ end
108
+
109
+ def test_delete
110
+ users = create_users
111
+ add_users(users)
112
+
113
+ users.open_cursor(:limit => 20) do |cursor|
114
+ 20.times do
115
+ cursor.next
116
+ cursor.delete
117
+ end
118
+ end
119
+
120
+ results = []
121
+ users.open_cursor do |cursor|
122
+ cursor.each do |record|
123
+ results << record["name"]
124
+ end
125
+ end
126
+
127
+ assert_equal((120...200).collect {|i| "user#{i}"},
128
+ results)
129
+ end
130
+
131
+ def test_patricia_trie_cursor_key
132
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
133
+ sites.add("http://groonga.org/")
134
+ sites.open_cursor do |cursor|
135
+ cursor.next
136
+ assert_equal("http://groonga.org/", cursor.key)
137
+ end
138
+ end
139
+
140
+ def test_order_by_id
141
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
142
+ sites.add("http://qwik.jp/senna/")
143
+ sites.add("http://www.ruby-lang.org/")
144
+ sites.add("http://groonga.org/")
145
+ keys = []
146
+ sites.open_cursor(:order_by => :id) do |cursor|
147
+ while cursor.next
148
+ keys << cursor.key
149
+ end
150
+ end
151
+ assert_equal(["http://qwik.jp/senna/",
152
+ "http://www.ruby-lang.org/",
153
+ "http://groonga.org/"],
154
+ keys)
155
+ end
156
+
157
+ def test_order_by_key
158
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
159
+ sites.add("http://www.ruby-lang.org/")
160
+ sites.add("http://qwik.jp/senna/")
161
+ sites.add("http://groonga.org/")
162
+ keys = []
163
+ sites.open_cursor(:order_by => :key) do |cursor|
164
+ while cursor.next
165
+ keys << cursor.key
166
+ end
167
+ end
168
+ assert_equal(["http://groonga.org/",
169
+ "http://qwik.jp/senna/",
170
+ "http://www.ruby-lang.org/"],
171
+ keys)
172
+ end
173
+
174
+ def test_each_without_block
175
+ @bookmarks.open_cursor do |cursor|
176
+ keys = cursor.each.collect(&:key)
177
+ assert_equal(["Cutter", "Ruby", "groonga"], keys)
178
+ end
179
+ end
180
+ end
181
+
182
+ class EachTest < self
183
+ def test_default
184
+ keys = []
185
+ @bookmarks.each do |record|
186
+ keys << record.key
187
+ end
188
+ assert_equal(["Cutter", "Ruby", "groonga"],
189
+ keys)
190
+ end
191
+
192
+ def test_order_ascending
193
+ record_and_key_list = []
194
+ @bookmarks.each(:order => :ascending) do |record|
195
+ record_and_key_list << [record, record.key]
196
+ end
197
+ assert_equal([[@cutter_bookmark, "Cutter"],
198
+ [@ruby_bookmark, "Ruby"],
199
+ [@groonga_bookmark, "groonga"]],
200
+ record_and_key_list)
201
+ end
202
+
203
+ def test_without_limit_and_offset
204
+ users = create_users
205
+ add_users(users)
206
+ results = []
207
+ users.each do |record|
208
+ results << record["name"]
209
+ end
210
+
211
+ assert_equal((100..199).collect {|i| "user#{i}"},
212
+ results)
213
+ end
214
+
215
+ def test_with_limit
216
+ users = create_users
217
+ add_users(users)
218
+ results = []
219
+ users.each(:limit => 20) do |record|
220
+ results << record["name"]
221
+ end
222
+
223
+ assert_equal((100...120).collect {|i| "user#{i}"},
224
+ results)
225
+ end
226
+
227
+ def test_with_offset
228
+ users = create_users
229
+ add_users(users)
230
+ results = []
231
+ users.each(:offset => 20) do |record|
232
+ results << record["name"]
233
+ end
234
+
235
+ assert_equal((120...200).collect {|i| "user#{i}"},
236
+ results)
237
+ end
238
+
239
+ def test_with_limit_and_offset
240
+ users = create_users
241
+ add_users(users)
242
+ results = []
243
+ users.each(:limit => 20, :offset => 20) do |record|
244
+ results << record["name"]
245
+ end
246
+
247
+ assert_equal((120...140).collect {|i| "user#{i}"},
248
+ results)
249
+ end
250
+
251
+ def test_patricia_trie_cursor_key
252
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
253
+ sites.add("http://groonga.org/")
254
+ sites.each do |record|
255
+ assert_equal("http://groonga.org/", record.key)
256
+ end
257
+ end
258
+
259
+ def test_order_by_id
260
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
261
+ sites.add("http://qwik.jp/senna/")
262
+ sites.add("http://www.ruby-lang.org/")
263
+ sites.add("http://groonga.org/")
264
+ keys = []
265
+ sites.each(:order_by => :id) do |record|
266
+ keys << record.key
267
+ end
268
+ assert_equal(["http://qwik.jp/senna/",
269
+ "http://www.ruby-lang.org/",
270
+ "http://groonga.org/"],
271
+ keys)
272
+ end
273
+
274
+ def test_order_by_key
275
+ sites = Groonga::PatriciaTrie.create(:name => "Sites")
276
+ sites.add("http://www.ruby-lang.org/")
277
+ sites.add("http://qwik.jp/senna/")
278
+ sites.add("http://groonga.org/")
279
+ keys = []
280
+ sites.each(:order_by => :key) do |record|
281
+ keys << record.key
282
+ end
283
+ assert_equal(["http://groonga.org/",
284
+ "http://qwik.jp/senna/",
285
+ "http://www.ruby-lang.org/"],
286
+ keys)
287
+ end
288
+ end
289
+
290
+ private
291
+ def create_users
292
+ users = Groonga::Array.create(:name => "Users")
293
+ users.define_column("name", "ShortText")
294
+ users
295
+ end
296
+
297
+ def add_users(users)
298
+ (0...100).to_a.each do |i|
299
+ user = users.add
300
+ user["name"] = "user#{i + 100}"
301
+ end
302
+ users
303
+ end
304
+ end
@@ -0,0 +1,711 @@
1
+ # Copyright (C) 2009-2011 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 version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ class TableTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_database
20
+
21
+ def test_create
22
+ table_path = @tables_dir + "bookmarks"
23
+ assert_not_predicate(table_path, :exist?)
24
+ table = Groonga::PatriciaTrie.create(:name => "Bookmarks",
25
+ :path => table_path.to_s)
26
+ assert_equal("Bookmarks", table.name)
27
+ assert_predicate(table_path, :exist?)
28
+ end
29
+
30
+ def test_temporary
31
+ table = Groonga::PatriciaTrie.create
32
+ assert_nil(table.name)
33
+ assert_predicate(table, :temporary?)
34
+ assert_not_predicate(table, :persistent?)
35
+ assert_equal([], @tables_dir.children)
36
+ end
37
+
38
+ def test_define_column
39
+ table_path = @tables_dir + "bookmarks"
40
+ table = Groonga::Hash.create(:name => "Bookmarks",
41
+ :path => table_path.to_s)
42
+ column = table.define_column("name", "Text")
43
+ assert_equal("Bookmarks.name", column.name)
44
+ assert_equal(column, table.column("name"))
45
+ end
46
+
47
+ def test_temporary_table_define_column_default_persistent
48
+ table = Groonga::Hash.create
49
+ assert_raise(Groonga::InvalidArgument) do
50
+ table.define_column("name", "ShortText")
51
+ end
52
+ end
53
+
54
+ def test_temporary_table_define_index_column_default_persistent
55
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
56
+ terms = Groonga::Hash.create
57
+ assert_raise(Groonga::InvalidArgument) do
58
+ terms.define_index_column("url", bookmarks)
59
+ end
60
+ end
61
+
62
+ def test_define_column_default_persistent
63
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
64
+ real_name = bookmarks.define_column("real_name", "ShortText")
65
+ assert_predicate(real_name, :persistent?)
66
+ end
67
+
68
+ def test_define_column_not_persistent
69
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
70
+ real_name = bookmarks.define_column("real_name", "ShortText",
71
+ :persistent => false)
72
+ assert_predicate(real_name, :temporary?)
73
+ end
74
+
75
+ def test_define_column_not_persistent_and_path
76
+ column_path = @tables_dir + "bookmakrs.real_name.column"
77
+
78
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
79
+ message = "should not pass :path if :persistent is false: <#{column_path}>"
80
+ assert_raise(ArgumentError.new(message)) do
81
+ bookmarks.define_column("real_name", "ShortText",
82
+ :path => column_path.to_s,
83
+ :persistent => false)
84
+ end
85
+ end
86
+
87
+ def test_define_index_column_default_persistent
88
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
89
+ terms = Groonga::Hash.create(:name => "Terms")
90
+ real_name = terms.define_index_column("real_name", bookmarks)
91
+ assert_predicate(real_name, :persistent?)
92
+ end
93
+
94
+ def test_define_index_column_not_persistent
95
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
96
+ terms = Groonga::Hash.create(:name => "Terms")
97
+ real_name = terms.define_index_column("real_name", bookmarks,
98
+ :persistent => false)
99
+ assert_predicate(real_name, :temporary?)
100
+ end
101
+
102
+ def test_define_index_column_not_persistent_and_path
103
+ column_path = @tables_dir + "bookmakrs.real_name.column"
104
+
105
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
106
+ terms = Groonga::Hash.create(:name => "Terms")
107
+ message = "should not pass :path if :persistent is false: <#{column_path}>"
108
+ assert_raise(ArgumentError.new(message)) do
109
+ terms.define_index_column("real_name", bookmarks,
110
+ :path => column_path.to_s,
111
+ :persistent => false)
112
+ end
113
+ end
114
+
115
+ def test_define_index_column
116
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
117
+ bookmarks.define_column("content", "Text")
118
+ terms = Groonga::Hash.create(:name => "Terms")
119
+ terms.default_tokenizer = "TokenBigram"
120
+ index = terms.define_index_column("content_index", bookmarks,
121
+ :with_section => true,
122
+ :source => "Bookmarks.content")
123
+ bookmarks.add("google", :content => "Search engine")
124
+ assert_equal(["google"],
125
+ index.search("engine").collect {|record| record.key.key})
126
+ end
127
+
128
+ def test_column_nonexistent
129
+ table_path = @tables_dir + "bookmarks"
130
+ table = Groonga::Hash.create(:name => "Bookmarks",
131
+ :path => table_path.to_s)
132
+ assert_nil(table.column("nonexistent"))
133
+ end
134
+
135
+ def test_set_value
136
+ table_path = @tables_dir + "bookmarks"
137
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks",
138
+ :value_type => "Int32",
139
+ :path => table_path.to_s)
140
+ comment_column_path = @columns_dir + "comment"
141
+ bookmarks_comment =
142
+ bookmarks.define_column("comment", "ShortText",
143
+ :type => "scalar",
144
+ :path => comment_column_path.to_s)
145
+ groonga = bookmarks.add("groonga")
146
+ groonga.value = 29
147
+ bookmarks_comment[groonga.id] = "fulltext search engine"
148
+
149
+ assert_equal([29, "fulltext search engine"],
150
+ [groonga.value, bookmarks_comment[groonga.id]])
151
+ end
152
+
153
+ def test_array_set
154
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks",
155
+ :value_type => "Int32")
156
+ bookmarks.set_value("groonga", 29)
157
+
158
+ values = bookmarks.records.collect do |record|
159
+ record.value
160
+ end
161
+ assert_equal([29], values)
162
+ end
163
+
164
+ def test_add_without_name
165
+ users_path = @tables_dir + "users"
166
+ users = Groonga::Array.create(:name => "Users",
167
+ :path => users_path.to_s)
168
+ name_column_path = @columns_dir + "name"
169
+ users_name = users.define_column("name", "ShortText",
170
+ :path => name_column_path.to_s)
171
+ morita = users.add
172
+ users_name[morita.id] = "morita"
173
+ assert_equal("morita", users_name[morita.id])
174
+ end
175
+
176
+ def test_add_by_id
177
+ users_path = @tables_dir + "users"
178
+ users = Groonga::Hash.create(:name => "Users",
179
+ :path => users_path.to_s)
180
+
181
+ bookmarks_path = @tables_dir + "bookmarks"
182
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks",
183
+ :key_type => users,
184
+ :value_type => "Int32",
185
+ :path => bookmarks_path.to_s)
186
+ morita = users.add("morita")
187
+ groonga = bookmarks.add(morita.id)
188
+ groonga.value = 29
189
+ assert_equal(29, groonga.value)
190
+ end
191
+
192
+ def test_add_vector_column_referencing_to_normalized_table_indexed_via_column_value
193
+ people = Groonga::Hash.create(:name => "People", :key_normalize => true)
194
+ movies = Groonga::Hash.create(:name => "Movies")
195
+ movies.define_column("casts", people, :type => :vector)
196
+ people.define_index_column("index", movies)
197
+
198
+ movies.add("DOCUMENTARY of AKB48", :casts => ["AKB48"])
199
+
200
+ people_records = people.records.collect(&:key)
201
+ assert_equal(["akb48"], people_records)
202
+ end
203
+
204
+ def test_add_vector_column_referencing_to_normalized_table_indexed_via_source
205
+ people = Groonga::Hash.create(:name => "People", :key_normalize => true)
206
+ movies = Groonga::Hash.create(:name => "Movies")
207
+ movies.define_column("casts", people, :type => :vector)
208
+ people.define_index_column("index", movies, :source => "casts")
209
+
210
+ movies.add("DOCUMENTARY of AKB48", :casts => ["AKB48"])
211
+
212
+ people_records = people.records.collect(&:key)
213
+ assert_equal(["akb48"], people_records)
214
+ end
215
+
216
+ def test_columns
217
+ bookmarks_path = @tables_dir + "bookmarks"
218
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
219
+ :path => bookmarks_path.to_s)
220
+
221
+ uri_column = bookmarks.define_column("uri", "ShortText")
222
+ comment_column = bookmarks.define_column("comment", "Text")
223
+ assert_equal([uri_column.name, comment_column.name].sort,
224
+ bookmarks.columns.collect {|column| column.name}.sort)
225
+ end
226
+
227
+ def test_column_by_symbol
228
+ bookmarks_path = @tables_dir + "bookmarks"
229
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
230
+ :path => bookmarks_path.to_s)
231
+
232
+ uri_column = bookmarks.define_column("uri", "Text")
233
+ assert_equal(uri_column, bookmarks.column(:uri))
234
+ end
235
+
236
+ def test_size
237
+ bookmarks_path = @tables_dir + "bookmarks"
238
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
239
+ :path => bookmarks_path.to_s)
240
+
241
+ assert_equal(0, bookmarks.size)
242
+
243
+ bookmarks.add
244
+ bookmarks.add
245
+ bookmarks.add
246
+
247
+ assert_equal(3, bookmarks.size)
248
+ end
249
+
250
+ def test_empty?
251
+ bookmarks_path = @tables_dir + "bookmarks"
252
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
253
+ :path => bookmarks_path.to_s)
254
+
255
+ assert_predicate(bookmarks, :empty?)
256
+ bookmarks.add
257
+ assert_not_predicate(bookmarks, :empty?)
258
+ end
259
+
260
+ def test_path
261
+ bookmarks_path = @tables_dir + "bookmarks"
262
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
263
+ :path => bookmarks_path.to_s)
264
+ assert_equal(bookmarks_path.to_s, bookmarks.path)
265
+ end
266
+
267
+ def test_time_column
268
+ bookmarks_path = @tables_dir + "bookmarks"
269
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
270
+ :path => bookmarks_path.to_s)
271
+ bookmarks.define_column("created_at", "Time")
272
+
273
+ bookmark = bookmarks.add
274
+ now = Time.now
275
+ bookmark["created_at"] = now
276
+ assert_equal(now.to_a,
277
+ bookmark["created_at"].to_a)
278
+ end
279
+
280
+ def test_delete
281
+ bookmarks_path = @tables_dir + "bookmarks"
282
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
283
+ :path => bookmarks_path.to_s)
284
+
285
+ bookmark_records = []
286
+ bookmark_records << bookmarks.add
287
+ bookmark_records << bookmarks.add
288
+ bookmark_records << bookmarks.add
289
+
290
+ assert_equal(3, bookmarks.size)
291
+ bookmarks.delete(bookmark_records[1].id)
292
+ assert_equal(2, bookmarks.size)
293
+ end
294
+
295
+ def test_remove
296
+ bookmarks_path = @tables_dir + "bookmarks"
297
+ bookmarks = Groonga::Array.create(:name => "Bookmarks",
298
+ :path => bookmarks_path.to_s)
299
+ assert_predicate(bookmarks_path, :exist?)
300
+ bookmarks.remove
301
+ assert_not_predicate(bookmarks_path, :exist?)
302
+ end
303
+
304
+ def test_temporary_add
305
+ table = Groonga::Hash.create(:key_type => "ShortText")
306
+ assert_equal(0, table.size)
307
+ table.add("key")
308
+ assert_equal(1, table.size)
309
+ end
310
+
311
+ def test_truncate
312
+ users = Groonga::Array.create(:name => "Users")
313
+ users.add
314
+ users.add
315
+ users.add
316
+ assert_equal(3, users.size)
317
+ assert_nothing_raised do
318
+ users.truncate
319
+ end
320
+ assert_equal(0, users.size)
321
+ end
322
+
323
+ def test_sort
324
+ bookmarks = create_bookmarks
325
+ add_shuffled_ids(bookmarks)
326
+
327
+ results = bookmarks.sort([
328
+ {
329
+ :key => "id",
330
+ :order => :descending,
331
+ },
332
+ ],
333
+ :limit => 20)
334
+ assert_equal((180..199).to_a.reverse,
335
+ results.collect {|record| record["id"]})
336
+ end
337
+
338
+ def test_sort_simple
339
+ bookmarks = create_bookmarks
340
+ add_shuffled_ids(bookmarks)
341
+
342
+ results = bookmarks.sort(["id"], :limit => 20)
343
+ assert_equal((100..119).to_a,
344
+ results.collect {|record| record["id"]})
345
+ end
346
+
347
+ def test_sort_by_array
348
+ bookmarks = create_bookmarks
349
+ add_shuffled_ids(bookmarks)
350
+
351
+ results = bookmarks.sort([["id", "descending"]], :limit => 20)
352
+ assert_equal((180..199).to_a.reverse,
353
+ results.collect {|record| record["id"]})
354
+ end
355
+
356
+ def test_sort_without_limit_and_offset
357
+ bookmarks = create_bookmarks
358
+ add_shuffled_ids(bookmarks)
359
+
360
+ results = bookmarks.sort([{:key => "id", :order => :descending}])
361
+ assert_equal((100..199).to_a.reverse,
362
+ results.collect {|record| record["id"]})
363
+ end
364
+
365
+ def test_sort_with_limit
366
+ bookmarks = create_bookmarks
367
+ add_shuffled_ids(bookmarks)
368
+
369
+ results = bookmarks.sort([{:key => "id", :order => :descending}],
370
+ :limit => 20)
371
+ assert_equal((180..199).to_a.reverse,
372
+ results.collect {|record| record["id"]})
373
+ end
374
+
375
+ def test_sort_with_offset
376
+ bookmarks = create_bookmarks
377
+ add_shuffled_ids(bookmarks)
378
+
379
+ results = bookmarks.sort([{:key => "id", :order => :descending}],
380
+ :offset => 20)
381
+ assert_equal((100..179).to_a.reverse,
382
+ results.collect {|record| record["id"]})
383
+ end
384
+
385
+ def test_sort_with_limit_and_offset
386
+ bookmarks = create_bookmarks
387
+ add_shuffled_ids(bookmarks)
388
+
389
+ results = bookmarks.sort([{:key => "id", :order => :descending}],
390
+ :limit => 20, :offset => 20)
391
+ assert_equal((160..179).to_a.reverse,
392
+ results.collect {|record| record["id"]})
393
+ end
394
+
395
+ def test_sort_with_nonexistent_key
396
+ bookmarks = create_bookmarks
397
+ add_shuffled_ids(bookmarks)
398
+ message = "no such column: <\"nonexistent\">: <#{bookmarks.inspect}>"
399
+ assert_raise(Groonga::NoSuchColumn.new(message)) do
400
+ bookmarks.sort([{:key => "nonexistent", :order => :descending}])
401
+ end
402
+ end
403
+
404
+ def test_sort_with_nonexistent_value
405
+ bookmarks = create_bookmarks
406
+ bookmarks.define_column("uri", "ShortText")
407
+ empty1 = bookmarks.add
408
+ groonga = bookmarks.add(:uri => "http://groonga.org/")
409
+ empty2 = bookmarks.add
410
+ assert_equal([groonga, empty1, empty2],
411
+ bookmarks.sort([{:key => "uri", :order => :descending}]))
412
+ end
413
+
414
+ def test_group
415
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
416
+ bookmarks.define_column("title", "Text")
417
+ comments = Groonga::Array.create(:name => "Comments")
418
+ comments.define_column("bookmark", bookmarks)
419
+ comments.define_column("content", "Text")
420
+ comments.define_column("issued", "Int32")
421
+
422
+ groonga = bookmarks.add("http://groonga.org/", :title => "groonga")
423
+ ruby = bookmarks.add("http://ruby-lang.org/", :title => "Ruby")
424
+
425
+ now = Time.now.to_i
426
+ comments.add(:bookmark => groonga,
427
+ :content => "full-text search",
428
+ :issued => now)
429
+ comments.add(:bookmark => groonga,
430
+ :content => "column store",
431
+ :issued => now)
432
+ comments.add(:bookmark => ruby,
433
+ :content => "object oriented script language",
434
+ :issued => now)
435
+
436
+ records = comments.select do |record|
437
+ record["issued"] > 0
438
+ end
439
+ assert_equal([[2, "groonga", "http://groonga.org/"],
440
+ [1, "Ruby", "http://ruby-lang.org/"]],
441
+ records.group(".bookmark").collect do |record|
442
+ bookmark = record.key
443
+ [record.n_sub_records,
444
+ bookmark["title"],
445
+ bookmark.key]
446
+ end)
447
+ assert_equal([[2, "groonga", "http://groonga.org/"],
448
+ [1, "Ruby", "http://ruby-lang.org/"]],
449
+ records.group(%w".bookmark").collect do |record|
450
+ bookmark = record.key
451
+ [record.n_sub_records,
452
+ bookmark["title"],
453
+ bookmark.key]
454
+ end)
455
+ end
456
+
457
+ def test_group_with_unknown_key
458
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
459
+ message = "unknown group key: <\"nonexistent\">: <#{bookmarks.inspect}>"
460
+ assert_raise(ArgumentError.new(message)) do
461
+ bookmarks.group("nonexistent")
462
+ end
463
+ end
464
+
465
+ def test_union!
466
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
467
+ bookmarks.define_column("title", "ShortText")
468
+
469
+ bookmarks.add("http://groonga.org/", :title => "groonga")
470
+ bookmarks.add("http://ruby-lang.org/", :title => "Ruby")
471
+
472
+ ruby_bookmarks = bookmarks.select {|record| record["title"] == "Ruby"}
473
+ groonga_bookmarks = bookmarks.select {|record| record["title"] == "groonga"}
474
+ assert_equal(["Ruby", "groonga"],
475
+ ruby_bookmarks.union!(groonga_bookmarks).collect do |record|
476
+ record[".title"]
477
+ end)
478
+ end
479
+
480
+ def test_intersection!
481
+ bookmarks = Groonga::Hash.create(:name => "bookmarks")
482
+ bookmarks.define_column("title", "ShortText")
483
+
484
+ bookmarks.add("http://groonga.org/", :title => "groonga")
485
+ bookmarks.add("http://ruby-lang.org/", :title => "Ruby")
486
+
487
+ ruby_bookmarks = bookmarks.select {|record| record["title"] == "Ruby"}
488
+ all_bookmarks = bookmarks.select
489
+ assert_equal(["Ruby"],
490
+ ruby_bookmarks.intersection!(all_bookmarks).collect do |record|
491
+ record[".title"]
492
+ end)
493
+ end
494
+
495
+ def test_difference!
496
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
497
+ bookmarks.define_column("title", "ShortText")
498
+
499
+ bookmarks.add("http://groonga.org/", :title => "groonga")
500
+ bookmarks.add("http://ruby-lang.org/", :title => "Ruby")
501
+
502
+ ruby_bookmarks = bookmarks.select {|record| record["title"] == "Ruby"}
503
+ all_bookmarks = bookmarks.select
504
+ assert_equal(["groonga"],
505
+ all_bookmarks.difference!(ruby_bookmarks).collect do |record|
506
+ record[".title"]
507
+ end)
508
+ end
509
+
510
+ def test_merge!
511
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
512
+ bookmarks.define_column("title", "ShortText")
513
+
514
+ bookmarks.add("http://groonga.org/", :title => "groonga")
515
+ bookmarks.add("http://ruby-lang.org/", :title => "Ruby")
516
+
517
+ ruby_bookmarks = bookmarks.select {|record| (record["title"] == "Ruby") &
518
+ (record["title"] == "Ruby") }
519
+ all_bookmarks = bookmarks.select
520
+ assert_equal([["groonga", 1], ["Ruby", 2]],
521
+ all_bookmarks.merge!(ruby_bookmarks).collect do |record|
522
+ [record[".title"], record.score]
523
+ end)
524
+ end
525
+
526
+ def test_lock
527
+ bookmarks = Groonga::Array.create(:name => "Bookmarks")
528
+ assert_not_predicate(bookmarks, :locked?)
529
+ bookmarks.lock
530
+ assert_predicate(bookmarks, :locked?)
531
+ bookmarks.unlock
532
+ assert_not_predicate(bookmarks, :locked?)
533
+ end
534
+
535
+ def test_lock_failed
536
+ bookmarks = Groonga::Array.create(:name => "Bookmarks")
537
+ bookmarks.lock
538
+ assert_raise(Groonga::ResourceDeadlockAvoided) do
539
+ bookmarks.lock
540
+ end
541
+ end
542
+
543
+ def test_lock_block
544
+ bookmarks = Groonga::Array.create(:name => "Bookmarks")
545
+ assert_not_predicate(bookmarks, :locked?)
546
+ bookmarks.lock do
547
+ assert_predicate(bookmarks, :locked?)
548
+ end
549
+ assert_not_predicate(bookmarks, :locked?)
550
+ end
551
+
552
+ def test_clear_lock
553
+ bookmarks = Groonga::Array.create(:name => "Bookmarks")
554
+ assert_not_predicate(bookmarks, :locked?)
555
+ bookmarks.lock
556
+ assert_predicate(bookmarks, :locked?)
557
+ bookmarks.clear_lock
558
+ assert_not_predicate(bookmarks, :locked?)
559
+ end
560
+
561
+ def test_auto_record_register
562
+ users = Groonga::Hash.create(:name => "Users",
563
+ :key_type => "ShortText")
564
+ books = Groonga::Hash.create(:name => "Books",
565
+ :key_type => "ShortText")
566
+ users.define_column("book", "Books")
567
+
568
+ assert_equal([], books.select.collect {|book| book.key})
569
+ users.add("ryoqun", :book => "XP")
570
+ assert_equal([books["XP"]],
571
+ books.select.collect {|book| book.key})
572
+ end
573
+
574
+ def test_get_common_prefix_column
575
+ users = Groonga::Array.create(:name => "Users")
576
+ users.define_column("name_kana", "ShortText")
577
+ name = users.define_column("name", "ShortText")
578
+
579
+ assert_equal(name, users.column("name"))
580
+ end
581
+
582
+ def test_empty_reference_column_value
583
+ users = Groonga::Hash.create(:name => "Users",
584
+ :key_type => "ShortText")
585
+ books = Groonga::Hash.create(:name => "Books",
586
+ :key_type => "ShortText")
587
+ users.define_column("book", books)
588
+ users.add("morita", :book => "")
589
+ assert_equal({"_id" => 1, "_key" => "morita", "book" => nil},
590
+ users["morita"].attributes)
591
+ end
592
+
593
+ def test_have_column
594
+ users = Groonga::Hash.create(:name => "Users",
595
+ :key_type => "ShortText")
596
+ users.define_column("name", "ShortText")
597
+ assert_true(users.have_column?("name"), "name")
598
+ assert_false(users.have_column?("description"), "description")
599
+ end
600
+
601
+ def test_have_column_id
602
+ users = Groonga::Array.create(:name => "Users")
603
+ assert_true(users.have_column?(:_id))
604
+ end
605
+
606
+ def test_have_column_key_hash
607
+ users = Groonga::Hash.create(:name => "Users",
608
+ :key_type => "ShortText")
609
+ assert_true(users.have_column?(:_key))
610
+ end
611
+
612
+ def test_have_column_key_array
613
+ users = Groonga::Array.create(:name => "Users")
614
+ assert_false(users.have_column?(:_key))
615
+ end
616
+
617
+ def test_have_column_value_hash_with_value_type
618
+ users = Groonga::Hash.create(:name => "Users",
619
+ :key_type => "ShortText",
620
+ :value_type => "Int32")
621
+ assert_true(users.have_column?(:_value))
622
+ end
623
+
624
+ def test_have_column_value_hash_without_value_type
625
+ users = Groonga::Hash.create(:name => "Users",
626
+ :key_type => "ShortText")
627
+ assert_false(users.have_column?(:_value))
628
+ end
629
+
630
+ def test_have_column_value_array
631
+ users = Groonga::Array.create(:name => "Users")
632
+ assert_false(users.have_column?(:_value))
633
+ end
634
+
635
+ def test_have_column_nsubrecs_existent
636
+ users = Groonga::Hash.create(:name => "Users",
637
+ :key_type => "ShortText")
638
+ assert_true(users.select.have_column?(:_nsubrecs))
639
+ end
640
+
641
+ def test_have_column_nsubrecs_nonexistent
642
+ users = Groonga::Hash.create(:name => "Users",
643
+ :key_type => "ShortText")
644
+ assert_false(users.have_column?(:_nsubrecs))
645
+ end
646
+
647
+ def test_have_column_score_existent
648
+ users = Groonga::Hash.create(:name => "Users",
649
+ :key_type => "ShortText")
650
+ assert_true(users.select.have_column?(:_score))
651
+ end
652
+
653
+ def test_have_column_score_nonexistent
654
+ users = Groonga::Hash.create(:name => "Users",
655
+ :key_type => "ShortText")
656
+ assert_false(users.have_column?(:_score))
657
+ end
658
+
659
+ def test_exist?
660
+ users = Groonga::Hash.create(:name => "Users")
661
+ morita = users.add("morita")
662
+ assert_true(users.exist?(morita.id))
663
+ assert_false(users.exist?(morita.id + 1))
664
+ end
665
+
666
+ def test_builtin?
667
+ bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks")
668
+ assert_not_predicate(bookmarks, :builtin?)
669
+ end
670
+
671
+ class OtherProcessTest < self
672
+ def test_create
673
+ by_other_process do
674
+ Groonga::PatriciaTrie.create(:name => "Bookmarks")
675
+ end
676
+ assert_not_nil(Groonga["Bookmarks"])
677
+ end
678
+
679
+ def test_define_column
680
+ bookmarks = Groonga::Hash.create(:name => "Bookmarks")
681
+ by_other_process do
682
+ bookmarks.define_column("name", "Text")
683
+ end
684
+ assert_not_nil(bookmarks.column("name"))
685
+ end
686
+
687
+ private
688
+ def by_other_process
689
+ pid = Process.fork do
690
+ yield
691
+ end
692
+ Process.waitpid(pid)
693
+ end
694
+ end
695
+
696
+ private
697
+ def create_bookmarks
698
+ bookmarks = Groonga::Array.create(:name => "Bookmarks")
699
+ bookmarks.define_column("id", "Int32")
700
+ bookmarks
701
+ end
702
+
703
+ def add_shuffled_ids(bookmarks)
704
+ srand(Time.now.to_i)
705
+ (0...100).to_a.shuffle.each do |i|
706
+ bookmark = bookmarks.add
707
+ bookmark["id"] = i + 100
708
+ end
709
+ bookmarks
710
+ end
711
+ end