rroonga 0.9.2-x86-mingw32

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 (199) hide show
  1. data/AUTHORS +5 -0
  2. data/NEWS.ja.rdoc +114 -0
  3. data/NEWS.rdoc +116 -0
  4. data/README.ja.rdoc +65 -0
  5. data/README.rdoc +66 -0
  6. data/Rakefile +206 -0
  7. data/benchmark/common.rb +49 -0
  8. data/benchmark/read-write-many-small-items.rb +144 -0
  9. data/benchmark/write-many-small-items.rb +135 -0
  10. data/example/bookmark.rb +161 -0
  11. data/example/index-html.rb +89 -0
  12. data/example/search/config.ru +230 -0
  13. data/example/search/public/css/groonga.css +122 -0
  14. data/ext/.gitignore +2 -0
  15. data/ext/groonga/extconf.rb +93 -0
  16. data/ext/groonga/rb-grn-accessor.c +52 -0
  17. data/ext/groonga/rb-grn-array-cursor.c +36 -0
  18. data/ext/groonga/rb-grn-array.c +210 -0
  19. data/ext/groonga/rb-grn-column.c +573 -0
  20. data/ext/groonga/rb-grn-context.c +662 -0
  21. data/ext/groonga/rb-grn-database.c +472 -0
  22. data/ext/groonga/rb-grn-encoding-support.c +64 -0
  23. data/ext/groonga/rb-grn-encoding.c +257 -0
  24. data/ext/groonga/rb-grn-exception.c +1110 -0
  25. data/ext/groonga/rb-grn-expression-builder.c +75 -0
  26. data/ext/groonga/rb-grn-expression.c +731 -0
  27. data/ext/groonga/rb-grn-fix-size-column.c +166 -0
  28. data/ext/groonga/rb-grn-hash-cursor.c +38 -0
  29. data/ext/groonga/rb-grn-hash.c +294 -0
  30. data/ext/groonga/rb-grn-index-column.c +488 -0
  31. data/ext/groonga/rb-grn-logger.c +504 -0
  32. data/ext/groonga/rb-grn-object.c +1369 -0
  33. data/ext/groonga/rb-grn-operation.c +198 -0
  34. data/ext/groonga/rb-grn-patricia-trie-cursor.c +39 -0
  35. data/ext/groonga/rb-grn-patricia-trie.c +488 -0
  36. data/ext/groonga/rb-grn-procedure.c +52 -0
  37. data/ext/groonga/rb-grn-query.c +260 -0
  38. data/ext/groonga/rb-grn-record.c +40 -0
  39. data/ext/groonga/rb-grn-snippet.c +334 -0
  40. data/ext/groonga/rb-grn-table-cursor-key-support.c +69 -0
  41. data/ext/groonga/rb-grn-table-cursor.c +247 -0
  42. data/ext/groonga/rb-grn-table-key-support.c +714 -0
  43. data/ext/groonga/rb-grn-table.c +1977 -0
  44. data/ext/groonga/rb-grn-type.c +181 -0
  45. data/ext/groonga/rb-grn-utils.c +769 -0
  46. data/ext/groonga/rb-grn-variable-size-column.c +36 -0
  47. data/ext/groonga/rb-grn-variable.c +108 -0
  48. data/ext/groonga/rb-grn-view-accessor.c +53 -0
  49. data/ext/groonga/rb-grn-view-cursor.c +35 -0
  50. data/ext/groonga/rb-grn-view-record.c +41 -0
  51. data/ext/groonga/rb-grn-view.c +421 -0
  52. data/ext/groonga/rb-grn.h +698 -0
  53. data/ext/groonga/rb-groonga.c +107 -0
  54. data/extconf.rb +130 -0
  55. data/html/bar.svg +153 -0
  56. data/html/developer.html +117 -0
  57. data/html/developer.svg +469 -0
  58. data/html/download.svg +253 -0
  59. data/html/favicon.ico +0 -0
  60. data/html/favicon.xcf +0 -0
  61. data/html/footer.html.erb +28 -0
  62. data/html/head.html.erb +4 -0
  63. data/html/header.html.erb +17 -0
  64. data/html/index.html +147 -0
  65. data/html/install.svg +636 -0
  66. data/html/logo.xcf +0 -0
  67. data/html/ranguba.css +250 -0
  68. data/html/tutorial.svg +559 -0
  69. data/lib/1.8/groonga.so +0 -0
  70. data/lib/1.9/groonga.so +0 -0
  71. data/lib/groonga.rb +90 -0
  72. data/lib/groonga/context.rb +184 -0
  73. data/lib/groonga/expression-builder.rb +324 -0
  74. data/lib/groonga/patricia-trie.rb +85 -0
  75. data/lib/groonga/record.rb +311 -0
  76. data/lib/groonga/schema.rb +1191 -0
  77. data/lib/groonga/view-record.rb +56 -0
  78. data/license/GPL +340 -0
  79. data/license/LGPL +504 -0
  80. data/license/RUBY +59 -0
  81. data/misc/grnop2ruby.rb +49 -0
  82. data/pkg-config.rb +333 -0
  83. data/rroonga-build.rb +57 -0
  84. data/test-unit/Rakefile +40 -0
  85. data/test-unit/TODO +5 -0
  86. data/test-unit/bin/testrb +5 -0
  87. data/test-unit/html/classic.html +15 -0
  88. data/test-unit/html/index.html +25 -0
  89. data/test-unit/html/index.html.ja +27 -0
  90. data/test-unit/lib/test/unit.rb +323 -0
  91. data/test-unit/lib/test/unit/assertionfailederror.rb +25 -0
  92. data/test-unit/lib/test/unit/assertions.rb +1230 -0
  93. data/test-unit/lib/test/unit/attribute.rb +125 -0
  94. data/test-unit/lib/test/unit/autorunner.rb +360 -0
  95. data/test-unit/lib/test/unit/collector.rb +36 -0
  96. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  97. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  98. data/test-unit/lib/test/unit/collector/load.rb +144 -0
  99. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  100. data/test-unit/lib/test/unit/color-scheme.rb +102 -0
  101. data/test-unit/lib/test/unit/color.rb +96 -0
  102. data/test-unit/lib/test/unit/diff.rb +724 -0
  103. data/test-unit/lib/test/unit/error.rb +130 -0
  104. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  105. data/test-unit/lib/test/unit/failure.rb +136 -0
  106. data/test-unit/lib/test/unit/fixture.rb +176 -0
  107. data/test-unit/lib/test/unit/notification.rb +129 -0
  108. data/test-unit/lib/test/unit/omission.rb +191 -0
  109. data/test-unit/lib/test/unit/pending.rb +150 -0
  110. data/test-unit/lib/test/unit/priority.rb +180 -0
  111. data/test-unit/lib/test/unit/runner/console.rb +52 -0
  112. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  113. data/test-unit/lib/test/unit/runner/tap.rb +8 -0
  114. data/test-unit/lib/test/unit/testcase.rb +476 -0
  115. data/test-unit/lib/test/unit/testresult.rb +89 -0
  116. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  117. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  118. data/test-unit/lib/test/unit/ui/console/testrunner.rb +466 -0
  119. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +63 -0
  120. data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
  121. data/test-unit/lib/test/unit/ui/testrunner.rb +28 -0
  122. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  123. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  124. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  125. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  126. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  127. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  128. data/test-unit/lib/test/unit/version.rb +7 -0
  129. data/test-unit/sample/adder.rb +13 -0
  130. data/test-unit/sample/subtracter.rb +12 -0
  131. data/test-unit/sample/test_adder.rb +20 -0
  132. data/test-unit/sample/test_subtracter.rb +20 -0
  133. data/test-unit/sample/test_user.rb +23 -0
  134. data/test-unit/test/collector/test-descendant.rb +133 -0
  135. data/test-unit/test/collector/test-load.rb +442 -0
  136. data/test-unit/test/collector/test_dir.rb +406 -0
  137. data/test-unit/test/collector/test_objectspace.rb +100 -0
  138. data/test-unit/test/run-test.rb +15 -0
  139. data/test-unit/test/test-attribute.rb +86 -0
  140. data/test-unit/test/test-color-scheme.rb +67 -0
  141. data/test-unit/test/test-color.rb +47 -0
  142. data/test-unit/test/test-diff.rb +518 -0
  143. data/test-unit/test/test-emacs-runner.rb +60 -0
  144. data/test-unit/test/test-fixture.rb +287 -0
  145. data/test-unit/test/test-notification.rb +33 -0
  146. data/test-unit/test/test-omission.rb +81 -0
  147. data/test-unit/test/test-pending.rb +70 -0
  148. data/test-unit/test/test-priority.rb +119 -0
  149. data/test-unit/test/test-testcase.rb +544 -0
  150. data/test-unit/test/test_assertions.rb +1151 -0
  151. data/test-unit/test/test_error.rb +26 -0
  152. data/test-unit/test/test_failure.rb +33 -0
  153. data/test-unit/test/test_testresult.rb +113 -0
  154. data/test-unit/test/test_testsuite.rb +129 -0
  155. data/test-unit/test/testunit-test-util.rb +14 -0
  156. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  157. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  158. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  159. data/test-unit/test/util/test_observable.rb +102 -0
  160. data/test-unit/test/util/test_procwrapper.rb +36 -0
  161. data/test/.gitignore +1 -0
  162. data/test/groonga-test-utils.rb +134 -0
  163. data/test/run-test.rb +58 -0
  164. data/test/test-array.rb +90 -0
  165. data/test/test-column.rb +316 -0
  166. data/test/test-context-select.rb +93 -0
  167. data/test/test-context.rb +73 -0
  168. data/test/test-database.rb +113 -0
  169. data/test/test-encoding.rb +33 -0
  170. data/test/test-exception.rb +93 -0
  171. data/test/test-expression-builder.rb +217 -0
  172. data/test/test-expression.rb +134 -0
  173. data/test/test-fix-size-column.rb +65 -0
  174. data/test/test-gqtp.rb +72 -0
  175. data/test/test-hash.rb +305 -0
  176. data/test/test-index-column.rb +81 -0
  177. data/test/test-logger.rb +37 -0
  178. data/test/test-patricia-trie.rb +205 -0
  179. data/test/test-procedure.rb +37 -0
  180. data/test/test-query.rb +22 -0
  181. data/test/test-record.rb +243 -0
  182. data/test/test-remote.rb +54 -0
  183. data/test/test-schema-view.rb +90 -0
  184. data/test/test-schema.rb +459 -0
  185. data/test/test-snippet.rb +130 -0
  186. data/test/test-table-cursor.rb +153 -0
  187. data/test/test-table-offset-and-limit.rb +102 -0
  188. data/test/test-table-select-normalize.rb +53 -0
  189. data/test/test-table-select.rb +150 -0
  190. data/test/test-table.rb +594 -0
  191. data/test/test-type.rb +71 -0
  192. data/test/test-variable-size-column.rb +98 -0
  193. data/test/test-variable.rb +28 -0
  194. data/test/test-vector-column.rb +76 -0
  195. data/test/test-version.rb +31 -0
  196. data/test/test-view.rb +72 -0
  197. data/text/TUTORIAL.ja.rdoc +392 -0
  198. data/text/expression.rdoc +284 -0
  199. metadata +276 -0
data/test/test-type.rb ADDED
@@ -0,0 +1,71 @@
1
+ # Copyright (C) 2009 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 TypeTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_database
20
+
21
+ def test_new
22
+ type = Groonga::Type.new("user_id", :type => :integer)
23
+ assert_equal("user_id", type.name)
24
+ end
25
+
26
+ def test_new_with_hyphen_name
27
+ exception = assert_raise(Groonga::InvalidArgument) do
28
+ Groonga::Type.new("user-id", :type => :integer)
29
+ end
30
+ message =
31
+ "name can't start with '_' and 0-9, and contains only 0-9, A-Z, a-z, or _"
32
+ assert_match(/#{Regexp.escape(message)}/,
33
+ exception.message)
34
+ end
35
+
36
+ def test_builtins
37
+ assert_equal_type("Object", Groonga::Type::OBJECT) # FIXME!!!
38
+ assert_equal_type("Bool", Groonga::Type::BOOLEAN)
39
+ assert_equal_type("Bool", Groonga::Type::BOOL)
40
+ assert_equal_type("Int8", Groonga::Type::INT8)
41
+ assert_equal_type("UInt8", Groonga::Type::UINT8)
42
+ assert_equal_type("Int16", Groonga::Type::INT16)
43
+ assert_equal_type("UInt16", Groonga::Type::UINT16)
44
+ assert_equal_type("Int32", Groonga::Type::INT32)
45
+ assert_equal_type("UInt32", Groonga::Type::UINT32)
46
+ assert_equal_type("Int64", Groonga::Type::INT64)
47
+ assert_equal_type("UInt64", Groonga::Type::UINT64)
48
+ assert_equal_type("Float", Groonga::Type::FLOAT)
49
+ assert_equal_type("Time", Groonga::Type::TIME)
50
+ assert_equal_type("ShortText", Groonga::Type::SHORT_TEXT)
51
+ assert_equal_type("Text", Groonga::Type::TEXT)
52
+ assert_equal_type("LongText", Groonga::Type::LONG_TEXT)
53
+ end
54
+
55
+ def test_inspect
56
+ assert_equal("#<Groonga::Type id: <#{Groonga::Type::LONG_TEXT}>, " +
57
+ "name: <LongText>, " +
58
+ "path: (temporary), " +
59
+ "domain: (nil), " +
60
+ "range: <2147483648>, " +
61
+ "flags: <>>",
62
+ context["<longtext>"].inspect)
63
+ end
64
+
65
+ private
66
+ def assert_equal_type(expected_name, id)
67
+ type = Groonga::Context.default[id]
68
+ assert_equal(expected_name,
69
+ type ? type.name : type)
70
+ end
71
+ end
@@ -0,0 +1,98 @@
1
+ # Copyright (C) 2009 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 VariableSizeColumnTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ def setup
20
+ setup_database
21
+
22
+ setup_users_table
23
+ setup_users
24
+ end
25
+
26
+ def setup_users_table
27
+ @users_path = @tables_dir + "users"
28
+ @users = Groonga::Array.create(:name => "Users",
29
+ :path => @users_path.to_s)
30
+
31
+ @users_name_column_path = @columns_dir + "name"
32
+ @name = @users.define_column("name", "ShortText",
33
+ :path => @users_name_column_path.to_s)
34
+
35
+ @users_friends_column_path = @columns_dir + "friends"
36
+ @friends = @users.define_column("friends", @users,
37
+ :type => :vector,
38
+ :path => @users_friends_column_path.to_s)
39
+
40
+ @users_nick_names_column_path = @columns_dir + "nick_names"
41
+ @nick_names =
42
+ @users.define_column("nick_names", "ShortText",
43
+ :type => :vector,
44
+ :path => @users_nick_names_column_path.to_s)
45
+ end
46
+
47
+ def setup_users
48
+ @morita = @users.add(:name => "mori daijiro")
49
+ @gunyara_kun = @users.add(:name => "Tasuku SUENAGA")
50
+ @yu = @users.add(:name => "Yutaro Shimamura")
51
+ end
52
+
53
+ def test_inspect
54
+ assert_equal("#<Groonga::VariableSizeColumn " +
55
+ "id: <#{@name.id}>, " +
56
+ "name: <Users.name>, " +
57
+ "path: <#{@users_name_column_path}>, " +
58
+ "domain: <Users>, " +
59
+ "range: <ShortText>, " +
60
+ "flags: <>" +
61
+ ">",
62
+ @name.inspect)
63
+ end
64
+
65
+ def test_domain
66
+ assert_equal(@users, @name.domain)
67
+ end
68
+
69
+ def test_table
70
+ assert_equal(@users, @name.table)
71
+ end
72
+
73
+ def test_vector_append
74
+ assert_equal([], @morita["friends"])
75
+ @morita.append("friends", @yu)
76
+ assert_equal([@yu], @morita["friends"])
77
+ @morita.append("friends", @gunyara_kun)
78
+ assert_equal([@yu, @gunyara_kun], @morita["friends"])
79
+ end
80
+
81
+ def test_vector_prepend
82
+ assert_equal([], @morita["friends"])
83
+ @morita.prepend("friends", @yu)
84
+ assert_equal([@yu], @morita["friends"])
85
+ @morita.prepend("friends", @gunyara_kun)
86
+ assert_equal([@gunyara_kun, @yu], @morita["friends"])
87
+ end
88
+
89
+ def test_string_vector
90
+ omit("append/prepend for non table domain column " +
91
+ "isn't supported by groonga.")
92
+ assert_equal([], @morita["nick_names"])
93
+ @morita.append("nick_names", "morita")
94
+ assert_equal(["morita"], @morita["nick_names"])
95
+ @morita.prepend("nick_names", "moritapo")
96
+ assert_equal(["moritapo", "morita"], @morita["nick_names"])
97
+ end
98
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright (C) 2009 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 VariableTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_database
20
+
21
+ def test_value
22
+ expression = Groonga::Expression.new
23
+ variable = expression.define_variable
24
+ assert_nil(variable.value)
25
+ variable.value = "morita"
26
+ assert_equal("morita", variable.value)
27
+ end
28
+ end
@@ -0,0 +1,76 @@
1
+ # Copyright (C) 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 VectorColumnTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ def setup
20
+ setup_database
21
+ setup_tables
22
+ end
23
+
24
+ def setup_tables
25
+ Groonga::Schema.define do |schema|
26
+ schema.create_table("Users",
27
+ :type => :hash,
28
+ :key_type => "UInt32") do |table|
29
+ end
30
+
31
+ schema.create_table("Communities",
32
+ :type => :hash,
33
+ :key_type => "ShortText") do |table|
34
+ table.reference("users", "Users", :type => :vector)
35
+ end
36
+
37
+ schema.create_table("Areas",
38
+ :type => :hash,
39
+ :key_type => "ShortText") do |table|
40
+ table.reference("communities", "Communities", :type => :vector)
41
+ end
42
+ end
43
+
44
+ @users = Groonga::Context.default["Users"]
45
+ @communities = Groonga::Context.default["Communities"]
46
+ @areas = Groonga::Context.default["Areas"]
47
+ end
48
+
49
+ def test_set_records
50
+ groonga = @communities.add("groonga")
51
+ morita = @users.add(29)
52
+ groonga["users"] = [morita]
53
+
54
+ assert_equal([29], @users.collect {|record| record.key})
55
+ assert_equal([29], groonga["users"].collect {|record| record.key})
56
+ end
57
+
58
+ def test_set_nonexistent_keys
59
+ shinjuku = @areas.add("Shinjuku")
60
+ shinjuku["communities"] = ["groonga", "Senna"]
61
+
62
+ assert_equal(["groonga", "Senna"],
63
+ @communities.collect {|record| record.key})
64
+ assert_equal(["groonga", "Senna"],
65
+ shinjuku["communities"].collect {|record| record.key})
66
+ end
67
+
68
+ def test_set_nil
69
+ groonga = @communities.add("groonga")
70
+ assert_equal([], groonga["users"])
71
+ groonga["users"] = nil
72
+ assert_equal([], groonga["users"]) # should return nil?
73
+ # Can groonga tell us
74
+ # that the value is empty?
75
+ end
76
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright (C) 2009 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 VersionTest < Test::Unit::TestCase
17
+ def test_build_version
18
+ assert_match(/\A\d+\.\d+\.\d+\z/, Groonga.build_version)
19
+ assert_match(Groonga.build_version, Groonga::BUILD_VERSION.join("."))
20
+ end
21
+
22
+ def test_version
23
+ assert_match(/\A\d+\.\d+\.\d+\z/, Groonga.version)
24
+ assert_match(Groonga.version, Groonga::VERSION.join("."))
25
+ end
26
+
27
+ def test_bindings_version
28
+ assert_match(/\A\d+\.\d+\.\d+\z/, Groonga.bindings_version)
29
+ assert_match(Groonga.bindings_version, Groonga::BINDINGS_VERSION.join("."))
30
+ end
31
+ end
data/test/test-view.rb ADDED
@@ -0,0 +1,72 @@
1
+ # Copyright (C) 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 ViewTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_database
20
+
21
+ def test_inspect
22
+ path = @tables_dir + "users.groonga"
23
+ view = Groonga::View.create(:name => "Users", :path => path.to_s)
24
+ assert_equal("#<Groonga::View " +
25
+ "id: <#{view.id}>, " +
26
+ "name: <Users>, " +
27
+ "path: <#{path}>, " +
28
+ "domain: (nil), " +
29
+ "range: (nil), " +
30
+ "flags: <>, " +
31
+ "encoding: <:default>, " +
32
+ "size: <0>>",
33
+ view.inspect)
34
+ end
35
+
36
+ def test_encoding
37
+ view = Groonga::View.create
38
+ assert_false(view.respond_to?(:encoding))
39
+ end
40
+
41
+ def test_add_table
42
+ users = Groonga::Array.create(:name => "Users")
43
+ dogs = Groonga::Array.create(:name => "Dogs")
44
+ entries = Groonga::View.create(:name => "Entries")
45
+ entries.add_table(users)
46
+ entries.add_table(dogs)
47
+
48
+ assert_equal(0, entries.size)
49
+ users.add
50
+ assert_equal(1, entries.size)
51
+ dogs.add
52
+ assert_equal(2, entries.size)
53
+ end
54
+
55
+ def test_sort
56
+ users = Groonga::Hash.create(:name => "Users", :key_type => "ShortText")
57
+ dogs = Groonga::Hash.create(:name => "Dogs", :key_type => "ShortText")
58
+ entries = Groonga::View.create(:name => "Entries")
59
+ entries.add_table(users)
60
+ entries.add_table(dogs)
61
+
62
+ users.add("morita")
63
+ users.add("tasuku")
64
+ users.add("yu")
65
+ dogs.add("pochi")
66
+ dogs.add("bob")
67
+ dogs.add("fuga")
68
+ omit("View#sort is broken!!!")
69
+ assert_equal(["XXX"],
70
+ entries.sort(["_key"], :limit => 2).collect {|entry| entry["_key"]})
71
+ end
72
+ end
@@ -0,0 +1,392 @@
1
+ = チュートリアル
2
+
3
+ このページでは簡単なアプリケーションの作成を通して
4
+ Ruby/groongaの操作方法を紹介します。
5
+
6
+ == インストール
7
+
8
+ Ruby/groongaはRubyGemsでインストールできます。
9
+
10
+ % sudo gem install groonga
11
+
12
+ == データベースの作成
13
+
14
+ 簡単なブックマークアプリケーション用のデータベースを作ってみ
15
+ ます。以下のようにgroongaライブラリを読み込んでirbを起動しま
16
+ す。
17
+
18
+ % irb --simple-prompt -rubygems -rgroonga
19
+ >>
20
+
21
+ まず、エンコーディングを設定します。ここではUTF-8を利用します。
22
+
23
+ >> $KCODE = "UTF-8"
24
+ => "UTF-8"
25
+ >> Groonga::Context.default_options = {:encoding => :utf8}
26
+ => {:encoding=>:utf8}
27
+
28
+ それでは、ファイルを指定してデータベースを作成します。
29
+
30
+ >> Groonga::Database.create(:path => "/tmp/bookmark.db")
31
+ => #<Groonga::Database ...>
32
+
33
+ ここで作成したデータベースは、これ以降、暗黙のうちに利用され
34
+ ます。最初にデータベースを作成したら特に意識する必要はありま
35
+ せん。
36
+
37
+ == テーブルの定義
38
+
39
+ groongaには以下の3種類のテーブルがあります。
40
+
41
+ [Groonga::Hash]
42
+ ハッシュテーブル。主キーでレコードを管理します。キーと完全
43
+ 一致するレコードを非常に高速に検索することができます。
44
+ [Groonga::PatriciaTrie]
45
+ パトリシアトライ。ハッシュテーブルに比べて完全一致検索の速
46
+ 度がやや遅いですが、前方一致検索・共通接頭辞探索などの検索
47
+ が行えます。またカーソルを用いてキーの昇降順にレコードを取
48
+ り出すことができます。
49
+ [Groonga::Array]
50
+ 配列。主キーの存在しないテーブルです。レコードはIDによって
51
+ 識別します。
52
+
53
+ ここではハッシュテーブルを利用して、<tt>Items</tt>という名前のテー
54
+ ブルを作成します。キーは文字列とします。
55
+
56
+ >> items = Groonga::Hash.create(:name => "Items", :key_type => "ShortText")
57
+ => #<Groonga::Hash ...>
58
+
59
+
60
+ これで<tt>Items</tt>という名前のテーブルが作成できました。
61
+
62
+ テーブルはRubyのHashのように扱えます。
63
+
64
+ 例えば、以下のように+size+でテーブルに登録されているレコード
65
+ の件数を取得できます。
66
+
67
+ >> items.size
68
+ 0
69
+
70
+ == レコードを追加する
71
+
72
+ <tt>Items</tt>テーブルにレコードを追加します。
73
+
74
+ >> items.add("http://ja.wikipedia.org/wiki/Ruby")
75
+ => #<Groonga::Record ...>
76
+ >> items.add("http://www.ruby-lang.org/")
77
+ => #<Groonga::Record ...>
78
+
79
+ 件数を確認すると確かに2件増えています。
80
+
81
+ >> items.size
82
+ => 2
83
+
84
+ 主キーを指定してレコードを取り出す時には以下のようにします。
85
+
86
+ >> items.find("http://ja.wikipedia.org/wiki/Ruby")
87
+ => #<Groonga::Record ...>
88
+
89
+ == 全文検索を行う
90
+
91
+ 各itemのタイトル文字列を登録して、全文検索できるようにしてみ
92
+ ましょう。
93
+
94
+ まず<tt>Items</tt>テーブルに+title+という名前のカラムを追加します。
95
+
96
+ >> title_column = items.define_column("title", "Text")
97
+ => #<Groonga::VarSizeColumn ...>
98
+
99
+ 2番目の引数は、追加するカラムのデータ型を示しています。
100
+ <tt><int></tt>、<tt>Text</tt>、<tt><longtext></tt>等の型が基本型として用意されて
101
+ います。
102
+
103
+ 全文検索するためには、文字列を分解して得られる各単語を格納す
104
+ るためのテーブルを別途しなければなりません。ここではTermsと
105
+ いう名前でテーブルを定義します。
106
+
107
+ >> terms = Groonga::Hash.create(:name => "Terms",
108
+ :key_type => "ShortText",
109
+ :default_tokenizer => "TokenBigram")
110
+ => #<Groonga::Hash ...>
111
+
112
+ ここでは、トークナイザとして<tt>:default_tokenzier =>
113
+ "TokenBigram"</tt> を指定しています。トークナイザとは文字
114
+ 列を単語に分解するオブジェクトのことです。デフォルトではトー
115
+ クナイザは指定されていません。全文検索を利用するためにはトー
116
+ クナイザを指定する必要があるので、ここではN-gramの一種である
117
+ バイグラムを指定しています。
118
+
119
+ N-gramを利用した全文検索では、分解したN文字とその出現位置を利
120
+ 用して全文検索を行います。N-gramのNは文字列を何文字毎に分解す
121
+ るかの文字数になります。groongaは1文字で分解するユニグラム、
122
+ 2文字のバイグラム、3文字のトリグラムをサポートしています。
123
+
124
+ 単語格納用テーブルの準備ができたので、<tt>Items</tt>テーブ
125
+ ルの+title+カラムに対するインデックスを定義します。
126
+
127
+ >> title_index_column = terms.define_index_column("item_title", items,
128
+ :source => "Items.title")
129
+ => #<Groonga::IndexColumn ...>
130
+
131
+ 少し違和感を感じるかも知れませんが、<tt>Items</tt>テーブル
132
+ のカラムに対するインデックスは、<tt>Terms</tt>テーブルのカ
133
+ ラムとして定義します。
134
+
135
+ <tt>Items</tt>にレコードが登録されると、その中に含まれる単
136
+ 語に該当するレコードが<tt>Terms</tt>に自動的に追加されるよ
137
+ うになります。
138
+
139
+ <tt>Terms</tt>は、文書に含まれる語彙に相当する、やや特殊な
140
+ テーブルだと言えます。しかし、他のテーブルと同様に語彙テーブ
141
+ ルには自由にカラムを追加し、単語毎の様々な属性を管理すること
142
+ ができます。これはある種の検索処理を行う際には非常に便利に機
143
+ 能します。
144
+
145
+ これでテーブルの定義は完了です。
146
+
147
+ 先ほど登録した各レコードの+title+カラムに値をセットします。
148
+
149
+ >> items.find("http://ja.wikipedia.org/wiki/Ruby")["title"] = "Ruby"
150
+ => "Ruby"
151
+ >> items.find("http://www.ruby-lang.org/")["title"] = "オブジェクトスクリプト言語Ruby"
152
+ "オブジェクトスクリプト言語Ruby"
153
+
154
+ 以下のようにして検索することができます。
155
+
156
+ >> title_index_column.search("Ruby").collect {|record| record.key.key}
157
+ ["http://ja.wikipedia.org/wiki/Ruby", "http://www.ruby-lang.org/"]
158
+
159
+ 検索結果はGroonga::Hashで返されます。ハッシュのキーに見つかっ
160
+ た<tt>Items</tt>のレコードが入っています。上の例では
161
+ +record.key+で<tt>Items</tt>のレコードを取得して、さらにそ
162
+ のキーを指定して(+record.key.key+)で<tt>Items</tt>のキー
163
+ を返しています。
164
+
165
+
166
+ == マルチユーザ向けのブックマークアプリケーション
167
+
168
+ ここまでで作った単機能のアプリケーションをもう少し拡張して、
169
+ 複数のユーザが、それぞれにコメントを記入できるブックマークア
170
+ プリケーションにしてみましょう。
171
+
172
+ まず、ユーザ情報とコメント情報を格納するテーブルを追加して、
173
+ 下図のようなテーブル構成にします。
174
+
175
+ http://qwik.jp/senna/senna2.files/rect4605.png
176
+
177
+ まず、<tt>Users</tt>テーブルを追加します。
178
+
179
+ >> users = Groonga::Hash.create(:name => "Users",
180
+ :key_type => "ShortText")
181
+ => #<Groonga::Hash ...>
182
+ >> users.define_column("name", "Text")
183
+ => #<Groonga::VarSizeColumn ...>
184
+
185
+
186
+ 次に、<tt>Comments</tt>テーブルを追加します。
187
+
188
+ >> comments = Groonga::Array.create(:name => "Comments")
189
+ => #<Groonga::Array ...>
190
+ >> comments.define_column("item", items)
191
+ => #<Groonga::FixSizeColumn ..>
192
+ >> comments.define_column("author", users)
193
+ => #<Groonga::FixSizeColumn ..>
194
+ >> comments.define_column("content", "Text")
195
+ => #<Groonga::VarSizeColumn ..>
196
+ >> comments.define_column("issued", "Time")
197
+ => #<Groonga::FixSizeColumn ..>
198
+
199
+ <tt>Comments</tt>テーブルの+content+カラムを全文検索できる
200
+ ようにインデックスを定義します。
201
+
202
+ >> terms.define_index_column("comment_content", comments,
203
+ :source => "Comments.content")
204
+ => #<Groonga::IndexColumn ...>
205
+
206
+ これでテーブルが定義できました。
207
+
208
+ 続いてユーザを何人か追加します。
209
+
210
+ >> users.add("moritan", :name => "モリタン")
211
+ => #<Groonga::Record ...>
212
+ >> users.add("taporobo", :name => "タポロボ")
213
+ => #<Groonga::Record ...>
214
+
215
+ 次に、実際にユーザがブックマークを貼る時の処理を実行してみま
216
+ しょう。
217
+
218
+ ユーザ+moritan+が、はてなダイアリーのとあるページをブックマーク
219
+ したと想定します。
220
+
221
+ まず対象のページが<tt>Items</tt>テーブルに登録済かどうか調
222
+ べます。
223
+
224
+ >> items.find("http://d.hatena.ne.jp/brazil/20050829/1125321936")
225
+ => nil
226
+
227
+ 未登録なのでまず当該ページを<tt>Items</tt>に登録します。
228
+
229
+ >> items.add("http://d.hatena.ne.jp/brazil/20050829/1125321936",
230
+ :title => "[翻訳]JavaScript: 世界で最も誤解されたプログラミング言語")
231
+ => #<Groonga::Record ...>
232
+
233
+ 次に、登録したitemを+item+カラムの値に指定して
234
+ <tt>Comments</tt>にレコードを登録します。
235
+
236
+ >> comments.add(:item => "http://d.hatena.ne.jp/brazil/20050829/1125321936",
237
+ :author => "moritan",
238
+ :content => "JavaScript LISP",
239
+ :issued => 1187430026)
240
+ => #<Groonga::Record ...>
241
+
242
+ == メソッド化
243
+
244
+ 上記の一連の手続きをメソッドにまとめてみます。
245
+
246
+ >> @items = items
247
+ >> @comments = comments
248
+ >> def add_bookmark(url, title, author, content, issued)
249
+ >> item = @items.find(url) || @items.add(url, :title => title)
250
+ >> @comments.add(:item => item,
251
+ >> :author => author,
252
+ >> :content => content,
253
+ >> :issued => issued)
254
+ >> end
255
+
256
+ +itmes+と+comments+をインスタンス変数に代入しているのはメソッ
257
+ ド内からでも見えるようにするためです。
258
+
259
+ +add_bookmark+は以下のような手順を実行しています。
260
+
261
+ * <tt>Items</tt>テーブルに該当ページのレコードがあるかどうか調べる。
262
+ * レコードがなければ追加する。
263
+ * <tt>Comments</tt>テーブルにレコードを登録する。
264
+
265
+ 作成したメソッドを呼び出していくつかブックマークを登録してみ
266
+ ましょう。
267
+
268
+ >> add_bookmark("http://practical-scheme.net/docs/cont-j.html",
269
+ "なんでも継続", "moritan", "継続 LISP Scheme", 1187568692)
270
+ => #<Groonga::Record ...>
271
+ >> add_bookmark("http://d.hatena.ne.jp/higepon/20070815/1187192864",
272
+ "末尾再帰", "taporobo", "末尾再帰 Scheme LISP", 1187568793)
273
+ => #<Groonga::Record ...>
274
+ >> add_bookmark("http://practical-scheme.net/docs/cont-j.html",
275
+ "なんでも継続", "taporobo", "トランポリン LISP continuation",
276
+ 1187568692)
277
+ => #<Groonga::Record ...>
278
+
279
+ == 全文検索その2
280
+
281
+ 登録したレコードに対して全文検索を実行してみます。
282
+
283
+ >> records = comments.select do |record|
284
+ >> record["content"] =~ "LISP"
285
+ >> end
286
+ >> records.each do |record|
287
+ >> record = record.key
288
+ >> p [record.id,
289
+ >> record[".issued"],
290
+ >> record[".item.title"],
291
+ >> record[".author.name"],
292
+ >> record[".content"]]
293
+ >> end
294
+ [1, Sat Aug 18 18:40:26 +0900 2007, "[翻訳]JavaScript: 世界で最も誤解されたプログラミング言語", "モリタン", "JavaScript LISP"]
295
+ [2, Mon Aug 20 09:11:32 +0900 2007, "なんでも継続", "モリタン", "継続 LISP Scheme"]
296
+ [3, Mon Aug 20 09:13:13 +0900 2007, "末尾再帰", "タポロボ", "末尾再帰 Scheme LISP"]
297
+ [4, Mon Aug 20 09:11:32 +0900 2007, "なんでも継続", "タポロボ", "トランポリン LISP continuation"]
298
+
299
+ カラムへのアクセスは、カラム名を+.+で繋いで複合データ型の要素
300
+ を再帰的に辿ることができます。(同様の出力を普通のRDBで実現す
301
+ るためには、<tt>Items</tt>テーブル、<tt>Comments</tt>テー
302
+ ブル、<tt>Users</tt>テーブルのJOIN操作が必要になります。)
303
+
304
+ 上の式の中で、肝心の検索処理は、第一引数の式を評価する時点で
305
+ 完了していて、レコードセットオブジェクトとしてメモリに蓄積さ
306
+ れています。
307
+
308
+ >> records
309
+ #<Groonga::Hash ..., size: <4>>
310
+
311
+ レコードセットは、出力する前に様々に加工することができます。
312
+
313
+ 以下は、日付で降順にソートしてから出力した例です。
314
+
315
+ >> records.sort([{:key => ".issued", :order => "descending"}]).each do |record|
316
+ >> record = record.key
317
+ >> p [record.id,
318
+ >> record[".issued"],
319
+ >> record[".item.title"],
320
+ >> record[".author.name"],
321
+ >> record[".content"]]
322
+ >> end
323
+ [3, Mon Aug 20 09:13:13 +0900 2007, "末尾再帰", "タポロボ", "末尾再帰 Scheme LISP"]
324
+ [2, Mon Aug 20 09:11:32 +0900 2007, "なんでも継続", "モリタン", "継続 LISP Scheme"]
325
+ [4, Mon Aug 20 09:11:32 +0900 2007, "なんでも継続", "タポロボ", "トランポリン LISP continuation"]
326
+ [1, Sat Aug 18 18:40:26 +0900 2007, "[翻訳]JavaScript: 世界で最も誤解されたプログラミング言語", "モリタン", "JavaScript LISP"]
327
+
328
+ 同じitemが何度も出てくると検索結果が見にくいので、item毎にグ
329
+ ループ化してみます。
330
+
331
+ >> records.group([".item"]).each do |record|
332
+ >> item = record.key
333
+ >> p [record.n_sub_records,
334
+ >> item.key,
335
+ >> item[".title"]]
336
+ >> end
337
+ [1, "http://d.hatena.ne.jp/brazil/20050829/1125321936", "[翻訳]JavaScript: 世界で最も誤解されたプログラミング言語"]
338
+ [2, "http://practical-scheme.net/docs/cont-j.html", "なんでも継続"]
339
+ [1, "http://d.hatena.ne.jp/higepon/20070815/1187192864", "末尾再帰"]
340
+
341
+ +n_sub_records+というのはグループ化した単位に含まれるレコード
342
+ の件数を示します。SQLで言えば、GROUP BY句を含むクエリのcount
343
+ 関数のような働きです。
344
+
345
+ == 少し複雑な検索
346
+
347
+ ↓はまだ動かない!!!
348
+
349
+ さらに実用的な検索について考えてみましょう。
350
+
351
+ ブックマークが大量に蓄積されるに従って、より的確に適合度を算
352
+ 出する必要性に迫られます。
353
+
354
+ 今のところ検索対象として利用できるのは<tt>Items.title</tt>
355
+ と<tt>Comments.content</tt>ですが、<tt>Items.title</tt>は
356
+ 元ページから得られるやや信頼できる情報なのに対して、
357
+ <tt>Comments.content</tt>はブックマークユーザが任意に設定で
358
+ きる情報で、やや信憑性に乏しいと言えます。しかし、再現率を確
359
+ 保するためにはユーザのコメントも是非対象に含めたいところです。
360
+
361
+ そこで、以下のようなポリシーで検索を行うことにします。
362
+
363
+ * <tt>Items.title</tt>か<tt>Comments.content</tt>のいずれ
364
+ かにマッチするitemを検索する。
365
+ * ただし、<tt>Items.title</tt>にマッチしたレコードはスコア
366
+ を10倍重み付けする。
367
+ * 同一のitemに対して、キーワードにマッチする<tt>comment</tt>
368
+ が複数存在した場合は、それぞれの<tt>comment</tt>のスコアの
369
+ 和を、該当するitemのスコアとする。
370
+
371
+ 以下のようにして、commentとitemとそれぞれに対する検索結果を求
372
+ めます。
373
+
374
+ >> ruby_comments = @comments.select {|record| record["content"] =~ "Ruby"}
375
+ #<Groonga::Hash ..., size: <2>>
376
+ >> ruby_items = @items.select("*W1:50 title:@Ruby")
377
+ #<Groonga::Hash ..., size: <2>>
378
+
379
+ _ruby_comments_の結果をitem毎にグループ化し、_ruby_items_と
380
+ unionして出力します。
381
+
382
+ >> ruby_items = ruby_comments.group([".item"]).union!(ruby_items)
383
+ #<Groonga::Hash ..., size: <4>>
384
+ >> ruby_items.sort([{:key => "._score", :order => "descendant"}]).each do |record|
385
+ >> p [record["._score"], record[".title"]]
386
+ >> end
387
+ [1, "るびま"]
388
+ [1, "オブジェクトスクリプト言語Ruby"]
389
+ [1, "Ruby"]
390
+ [1, "ラングバ"]
391
+
392
+ これで目的の結果が得られました。(FIXME: 得られていない!)