rroonga 1.2.9 → 1.3.0

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 (76) hide show
  1. data/Gemfile +1 -0
  2. data/Rakefile +1 -0
  3. data/bin/grntest-log-analyze +123 -0
  4. data/bin/groonga-query-log-extract +117 -0
  5. data/ext/groonga/rb-grn-accessor.c +7 -5
  6. data/ext/groonga/rb-grn-array-cursor.c +1 -1
  7. data/ext/groonga/rb-grn-array.c +34 -44
  8. data/ext/groonga/rb-grn-column.c +74 -38
  9. data/ext/groonga/rb-grn-context.c +19 -15
  10. data/ext/groonga/rb-grn-database.c +47 -42
  11. data/ext/groonga/rb-grn-double-array-trie-cursor.c +40 -0
  12. data/ext/groonga/rb-grn-double-array-trie.c +530 -0
  13. data/ext/groonga/rb-grn-encoding-support.c +1 -1
  14. data/ext/groonga/rb-grn-encoding.c +1 -1
  15. data/ext/groonga/rb-grn-exception.c +1 -1
  16. data/ext/groonga/rb-grn-expression-builder.c +1 -1
  17. data/ext/groonga/rb-grn-expression.c +63 -51
  18. data/ext/groonga/rb-grn-fix-size-column.c +7 -7
  19. data/ext/groonga/rb-grn-hash-cursor.c +1 -1
  20. data/ext/groonga/rb-grn-hash.c +42 -39
  21. data/ext/groonga/rb-grn-index-column.c +35 -31
  22. data/ext/groonga/rb-grn-index-cursor.c +1 -1
  23. data/ext/groonga/rb-grn-logger.c +23 -18
  24. data/ext/groonga/rb-grn-object.c +40 -27
  25. data/ext/groonga/rb-grn-operator.c +1 -1
  26. data/ext/groonga/rb-grn-patricia-trie-cursor.c +1 -1
  27. data/ext/groonga/rb-grn-patricia-trie.c +122 -90
  28. data/ext/groonga/rb-grn-plugin.c +8 -7
  29. data/ext/groonga/rb-grn-posting.c +1 -1
  30. data/ext/groonga/rb-grn-procedure.c +1 -1
  31. data/ext/groonga/rb-grn-query.c +12 -12
  32. data/ext/groonga/rb-grn-record.c +1 -1
  33. data/ext/groonga/rb-grn-snippet.c +26 -19
  34. data/ext/groonga/rb-grn-table-cursor-key-support.c +1 -1
  35. data/ext/groonga/rb-grn-table-cursor.c +4 -3
  36. data/ext/groonga/rb-grn-table-key-support.c +23 -23
  37. data/ext/groonga/rb-grn-table.c +268 -153
  38. data/ext/groonga/rb-grn-type.c +11 -7
  39. data/ext/groonga/rb-grn-utils.c +4 -1
  40. data/ext/groonga/rb-grn-variable-size-column.c +1 -1
  41. data/ext/groonga/rb-grn-variable.c +2 -2
  42. data/ext/groonga/rb-grn-view-accessor.c +1 -1
  43. data/ext/groonga/rb-grn-view-cursor.c +1 -1
  44. data/ext/groonga/rb-grn-view-record.c +1 -1
  45. data/ext/groonga/rb-grn-view.c +43 -34
  46. data/ext/groonga/rb-grn.h +6 -2
  47. data/ext/groonga/rb-groonga.c +1 -1
  48. data/lib/groonga.rb +4 -2
  49. data/lib/groonga/context.rb +16 -41
  50. data/lib/groonga/dumper.rb +6 -4
  51. data/lib/groonga/expression-builder.rb +52 -26
  52. data/lib/groonga/grntest-log.rb +206 -0
  53. data/lib/groonga/pagination.rb +21 -19
  54. data/lib/groonga/patricia-trie.rb +7 -10
  55. data/lib/groonga/posting.rb +1 -1
  56. data/lib/groonga/query-log.rb +348 -0
  57. data/lib/groonga/record.rb +47 -143
  58. data/lib/groonga/schema.rb +679 -406
  59. data/lib/groonga/view-record.rb +4 -10
  60. data/rroonga-build.rb +1 -1
  61. data/test/test-array.rb +25 -4
  62. data/test/test-column.rb +8 -8
  63. data/test/test-database.rb +2 -3
  64. data/test/test-double-array-trie.rb +164 -0
  65. data/test/test-expression-builder.rb +2 -2
  66. data/test/test-expression.rb +10 -9
  67. data/test/test-gqtp.rb +2 -2
  68. data/test/test-hash.rb +32 -8
  69. data/test/test-patricia-trie.rb +34 -10
  70. data/test/test-query-log.rb +258 -0
  71. data/test/test-record.rb +6 -5
  72. data/test/test-schema-create-table.rb +8 -0
  73. data/test/test-schema.rb +491 -234
  74. data/test/test-table.rb +17 -24
  75. metadata +123 -100
  76. data/ext/groonga/Makefile +0 -233
@@ -17,22 +17,19 @@
17
17
 
18
18
  module Groonga
19
19
  class PatriciaTrie
20
- # call-seq:
21
- # patricia_trie.tag_keys(text, options={}) {|record, word| ...} -> String
22
- #
23
- # _text_を走査し、レコードのキーとマッチする部分文字列ごとに
24
- # そのレコードが_record_として、その部分文字列が_word_として、
20
+ # _text_ を走査し、レコードのキーとマッチする部分文字列ごとに
21
+ # そのレコードが _record_ として、その部分文字列が _word_ として、
25
22
  # ブロックが呼び出される。ブロックから返された文字列が元の部
26
23
  # 分文字列と置換される。全てのヒットに対してのその置換処理が
27
24
  # 行われた文字列が返される。
28
25
  #
29
- # _options_に指定可能な値は以下の通り。
26
+ # @param options [::Hash] The name and value
27
+ # pairs. Omitted names are initialized as the default value.
28
+ # @option options [Proc] :other_text_handler The other_text_handler
30
29
  #
31
- # [+:other_text_handler+]
32
- # マッチした部分文字列の前後の文字列を変換するProcを指
33
- # 定する。
30
+ # マッチした部分文字列の前後の文字列を変換するProcを指定する。
34
31
  #
35
- # 例:
32
+ # @example
36
33
  # include ERB::Util
37
34
  # Groonga::Context.default_options = {:encoding => "utf-8"}
38
35
  # words = Groonga::PatriciaTrie.create(:key_type => "ShortText",
@@ -52,7 +52,7 @@ module Groonga
52
52
 
53
53
  # Updates all values.
54
54
  #
55
- # @param [Hash] parameters The name and value
55
+ # @param [::Hash] parameters The name and value
56
56
  # pairs. Omitted names are initialized as the default value.
57
57
  # @option parameters [Integer] :record_id The record_id.
58
58
  # @option parameters [Integer] :section_id The section_id.
@@ -0,0 +1,348 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "English"
19
+ require "shellwords"
20
+ require "cgi"
21
+
22
+ module Groonga
23
+ module QueryLog
24
+ class Command
25
+ class << self
26
+ @@registered_commands = {}
27
+ def register(name, klass)
28
+ @@registered_commands[name] = klass
29
+ end
30
+
31
+ def parse(input)
32
+ if input.start_with?("/d/")
33
+ parse_uri_path(input)
34
+ else
35
+ parse_command_line(input)
36
+ end
37
+ end
38
+
39
+ private
40
+ def parse_uri_path(path)
41
+ name, parameters_string = path.split(/\?/, 2)
42
+ parameters = {}
43
+ if parameters_string
44
+ parameters_string.split(/&/).each do |parameter_string|
45
+ key, value = parameter_string.split(/\=/, 2)
46
+ parameters[key] = CGI.unescape(value)
47
+ end
48
+ end
49
+ name = name.gsub(/\A\/d\//, '')
50
+ name, output_type = name.split(/\./, 2)
51
+ parameters["output_type"] = output_type if output_type
52
+ command_class = @@registered_commands[name] || self
53
+ command = command_class.new(name, parameters)
54
+ command.original_format = :uri
55
+ command
56
+ end
57
+
58
+ def parse_command_line(command_line)
59
+ name, *options = Shellwords.shellwords(command_line)
60
+ parameters = {}
61
+ options.each_slice(2) do |key, value|
62
+ parameters[key.gsub(/\A--/, '')] = value
63
+ end
64
+ command_class = @@registered_commands[name] || self
65
+ command = command_class.new(name, parameters)
66
+ command.original_format = :command
67
+ command
68
+ end
69
+ end
70
+
71
+ attr_reader :name, :parameters
72
+ attr_accessor :original_format
73
+ def initialize(name, parameters)
74
+ @name = name
75
+ @parameters = parameters
76
+ @original_format = nil
77
+ end
78
+
79
+ def ==(other)
80
+ other.is_a?(self.class) and
81
+ @name == other.name and
82
+ @parameters == other.parameters
83
+ end
84
+
85
+ def uri_format?
86
+ @original_format == :uri
87
+ end
88
+
89
+ def command_format?
90
+ @original_format == :command
91
+ end
92
+
93
+ def to_uri_format
94
+ path = "/d/#{@name}"
95
+ parameters = @parameters.dup
96
+ output_type = parameters.delete("output_type")
97
+ path << ".#{output_type}" if output_type
98
+ unless parameters.empty?
99
+ sorted_parameters = parameters.sort_by do |name, _|
100
+ name.to_s
101
+ end
102
+ uri_parameters = sorted_parameters.collect do |name, value|
103
+ "#{CGI.escape(name)}=#{CGI.escape(value)}"
104
+ end
105
+ path << "?"
106
+ path << uri_parameters.join("&")
107
+ end
108
+ path
109
+ end
110
+
111
+ def to_command_format
112
+ command_line = [@name]
113
+ sorted_parameters = @parameters.sort_by do |name, _|
114
+ name.to_s
115
+ end
116
+ sorted_parameters.each do |name, value|
117
+ escaped_value = value.gsub(/[\n"\\]/) do
118
+ special_character = $MATCH
119
+ case special_character
120
+ when "\n"
121
+ "\\n"
122
+ else
123
+ "\\#{special_character}"
124
+ end
125
+ end
126
+ command_line << "--#{name}"
127
+ command_line << "\"#{escaped_value}\""
128
+ end
129
+ command_line.join(" ")
130
+ end
131
+ end
132
+
133
+ class SelectCommand < Command
134
+ register("select", self)
135
+
136
+ def sortby
137
+ @parameters["sortby"]
138
+ end
139
+
140
+ def scorer
141
+ @parameters["scorer"]
142
+ end
143
+
144
+ def query
145
+ @parameters["query"]
146
+ end
147
+
148
+ def filter
149
+ @parameters["filter"]
150
+ end
151
+
152
+ def conditions
153
+ @conditions ||= filter.split(/(?:&&|&!|\|\|)/).collect do |condition|
154
+ condition = condition.strip
155
+ condition = condition.gsub(/\A[\s\(]*/, '')
156
+ condition = condition.gsub(/[\s\)]*\z/, '') unless /\(/ =~ condition
157
+ condition
158
+ end
159
+ end
160
+
161
+ def drilldowns
162
+ @drilldowns ||= (@parameters["drilldown"] || "").split(/\s*,\s*/)
163
+ end
164
+
165
+ def output_columns
166
+ @parameters["output_columns"]
167
+ end
168
+ end
169
+
170
+ class Statistic
171
+ attr_reader :context_id, :start_time, :raw_command
172
+ attr_reader :elapsed, :return_code
173
+ attr_accessor :slow_operation_threshold, :slow_response_threshold
174
+ def initialize(context_id)
175
+ @context_id = context_id
176
+ @start_time = nil
177
+ @command = nil
178
+ @raw_command = nil
179
+ @operations = []
180
+ @elapsed = nil
181
+ @return_code = 0
182
+ @slow_operation_threshold = 0.1
183
+ @slow_response_threshold = 0.2
184
+ end
185
+
186
+ def start(start_time, command)
187
+ @start_time = start_time
188
+ @raw_command = command
189
+ end
190
+
191
+ def finish(elapsed, return_code)
192
+ @elapsed = elapsed
193
+ @return_code = return_code
194
+ end
195
+
196
+ def command
197
+ @command ||= Command.parse(@raw_command)
198
+ end
199
+
200
+ def elapsed_in_seconds
201
+ nano_seconds_to_seconds(@elapsed)
202
+ end
203
+
204
+ def last_time
205
+ @start_time + elapsed_in_seconds
206
+ end
207
+
208
+ def slow?
209
+ elapsed_in_seconds >= @slow_response_threshold
210
+ end
211
+
212
+ def each_operation
213
+ previous_elapsed = 0
214
+ ensure_parse_command
215
+ operation_context_context = {
216
+ :filter_index => 0,
217
+ :drilldown_index => 0,
218
+ }
219
+ @operations.each_with_index do |operation, i|
220
+ relative_elapsed = operation[:elapsed] - previous_elapsed
221
+ relative_elapsed_in_seconds = nano_seconds_to_seconds(relative_elapsed)
222
+ previous_elapsed = operation[:elapsed]
223
+ parsed_operation = {
224
+ :i => i,
225
+ :elapsed => operation[:elapsed],
226
+ :elapsed_in_seconds => nano_seconds_to_seconds(operation[:elapsed]),
227
+ :relative_elapsed => relative_elapsed,
228
+ :relative_elapsed_in_seconds => relative_elapsed_in_seconds,
229
+ :name => operation[:name],
230
+ :context => operation_context(operation[:name],
231
+ operation_context_context),
232
+ :n_records => operation[:n_records],
233
+ :slow? => slow_operation?(relative_elapsed_in_seconds),
234
+ }
235
+ yield parsed_operation
236
+ end
237
+ end
238
+
239
+ def add_operation(operation)
240
+ @operations << operation
241
+ end
242
+
243
+ def operations
244
+ _operations = []
245
+ each_operation do |operation|
246
+ _operations << operation
247
+ end
248
+ _operations
249
+ end
250
+
251
+ def select_command?
252
+ command.name == "select"
253
+ end
254
+
255
+ private
256
+ def nano_seconds_to_seconds(nano_seconds)
257
+ nano_seconds / 1000.0 / 1000.0 / 1000.0
258
+ end
259
+
260
+ def operation_context(label, context)
261
+ case label
262
+ when "filter"
263
+ if @select_command.query and context[:query_used].nil?
264
+ context[:query_used] = true
265
+ "query: #{@select_command.query}"
266
+ else
267
+ index = context[:filter_index]
268
+ context[:filter_index] += 1
269
+ @select_command.conditions[index]
270
+ end
271
+ when "sort"
272
+ @select_command.sortby
273
+ when "score"
274
+ @select_command.scorer
275
+ when "output"
276
+ @select_command.output_columns
277
+ when "drilldown"
278
+ index = context[:drilldown_index]
279
+ context[:drilldown_index] += 1
280
+ @select_command.drilldowns[index]
281
+ else
282
+ nil
283
+ end
284
+ end
285
+
286
+ def ensure_parse_command
287
+ return unless select_command?
288
+ @select_command = SelectCommand.parse(@raw_command)
289
+ end
290
+
291
+ def slow_operation?(elapsed)
292
+ elapsed >= @slow_operation_threshold
293
+ end
294
+ end
295
+
296
+ class Parser
297
+ def initialize
298
+ end
299
+
300
+ def parse(input, &block)
301
+ current_statistics = {}
302
+ input.each_line do |line|
303
+ case line
304
+ when /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\.(\d+)\|(.+?)\|([>:<])/
305
+ year, month, day, hour, minutes, seconds, micro_seconds =
306
+ $1, $2, $3, $4, $5, $6, $7
307
+ context_id = $8
308
+ type = $9
309
+ rest = $POSTMATCH.strip
310
+ time_stamp = Time.local(year, month, day, hour, minutes, seconds,
311
+ micro_seconds)
312
+ parse_line(current_statistics,
313
+ time_stamp, context_id, type, rest, &block)
314
+ end
315
+ end
316
+ end
317
+
318
+ private
319
+ def parse_line(current_statistics,
320
+ time_stamp, context_id, type, rest, &block)
321
+ case type
322
+ when ">"
323
+ statistic = Statistic.new(context_id)
324
+ statistic.start(time_stamp, rest)
325
+ current_statistics[context_id] = statistic
326
+ when ":"
327
+ return unless /\A(\d+) (.+)\((\d+)\)/ =~ rest
328
+ elapsed = $1
329
+ name = $2
330
+ n_records = $3.to_i
331
+ statistic = current_statistics[context_id]
332
+ return if statistic.nil?
333
+ statistic.add_operation(:name => name,
334
+ :elapsed => elapsed.to_i,
335
+ :n_records => n_records)
336
+ when "<"
337
+ return unless /\A(\d+) rc=(\d+)/ =~ rest
338
+ elapsed = $1
339
+ return_code = $2
340
+ statistic = current_statistics.delete(context_id)
341
+ return if statistic.nil?
342
+ statistic.finish(elapsed.to_i, return_code.to_i)
343
+ block.call(statistic)
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
@@ -21,7 +21,7 @@ module Groonga
21
21
  class Record
22
22
  # レコードが所属するテーブル
23
23
  attr_reader :table
24
- # _table_の_id_に対応するレコードを作成する。_values_には各
24
+ # _table_ _id_ に対応するレコードを作成する。_values_ には各
25
25
  # カラムに設定する値を以下のような形式で指定する。
26
26
  #
27
27
  # [
@@ -40,141 +40,96 @@ module Groonga
40
40
  end
41
41
  end
42
42
 
43
- # call-seq:
44
- # record == other -> true/false
45
- #
46
- # _record_と_other_が同じテーブルに属していて、さらに、
47
- # 同じレコードIDを持つなら+true+を返し、そうでなければ
48
- # +false+を返す。
43
+ # _record_ と _other_ が同じテーブルに属していて、さらに、
44
+ # 同じレコードIDを持つなら +true+ を返し、そうでなければ
45
+ # +false+ を返す。
49
46
  def ==(other)
50
47
  self.class == other.class and
51
48
  [table, id] == [other.table, other.id]
52
49
  end
53
50
 
54
- # call-seq:
55
- # record.eql?(other) -> true/false
56
- #
57
51
  # Groonga::Record#==と同じ。
58
52
  def eql?(other)
59
53
  self == other
60
54
  end
61
55
 
62
- # call-seq:
63
- # record.hash -> ハッシュ値
64
- #
65
56
  # 同じテーブルの同じIDのレコードに対しては常に同じハッシュ
66
57
  # 値を返す。
67
58
  def hash
68
59
  @table.hash ^ @id.hash
69
60
  end
70
61
 
71
- # call-seq:
72
- # record[column_name] -> 値
73
- #
74
- # このレコードの_column_name_で指定されたカラムの値を返す。
62
+ # このレコードの _column_name_ で指定されたカラムの値を返す。
75
63
  def [](column_name)
76
64
  @table.column_value(@id, column_name, :id => true)
77
65
  end
78
66
 
79
- # call-seq:
80
- # record[column_name] = 値
81
- #
82
- # このレコードの_column_name_で指定されたカラムの値を設定す
67
+ # このレコードの _column_name_ で指定されたカラムの値を設定す
83
68
  # る。
84
69
  def []=(column_name, value)
85
70
  @table.set_column_value(@id, column_name, value, :id => true)
86
71
  end
87
72
 
88
- # call-seq:
89
- # record.append(column_name, value)
90
- #
91
- # このレコードの_column_name_で指定されたカラムの値の最後に
92
- # _value_を追加する。
73
+ # このレコードの _column_name_ で指定されたカラムの値の最後に
74
+ # _value_ を追加する。
93
75
  def append(column_name, value)
94
76
  column(column_name).append(@id, value)
95
77
  end
96
78
 
97
- # call-seq:
98
- # record.prepend(column_name, value)
99
- #
100
- # このレコードの_column_name_で指定されたカラムの値の最初に
101
- # _value_を追加する。
79
+ # このレコードの _column_name_ で指定されたカラムの値の最初に
80
+ # _value_ を追加する。
102
81
  def prepend(column_name, value)
103
82
  column(column_name).prepend(@id, value)
104
83
  end
105
84
 
106
- # call-seq:
107
- # record.support_key? -> true/false
108
- #
109
- # _record_が所属するテーブルで主キーを使える場合は+true+
110
- # を返し、使えない場合は+false+を返す。
85
+ # _record_ が所属するテーブルで主キーを使える場合は +true+
86
+ # を返し、使えない場合は +false+ を返す。
111
87
  def support_key?
112
88
  @table.support_key?
113
89
  end
114
90
 
115
- # call-seq:
116
- # record.have_column?(name) -> true/false
117
- #
118
- # 名前が_name_のカラムがレコードの所属するテーブルで定義され
119
- # ているなら+true+を返す。
91
+ # 名前が _name_ のカラムがレコードの所属するテーブルで定義され
92
+ # ているなら +true+ を返す。
120
93
  def have_column?(name)
121
94
  not @table.column(normalize_column_name(name)).nil?
122
95
  end
123
96
 
124
- # call-seq:
125
- # record.reference_column?(name) -> true/false
126
- #
127
- # 名前が_name_のカラムが参照カラムであるなら+true+を返す。
97
+ # 名前が _name_ のカラムが参照カラムであるなら +true+ を返す。
128
98
  def reference_column?(name)
129
99
  column(name).reference?
130
100
  end
131
101
 
132
- # call-seq:
133
- # record.index_column?(name) -> true/false
134
- #
135
- # 名前が_name_のカラムが索引カラム
136
- # (Groonga::IndexColumn)であるなら+true+を返す。
102
+ # 名前が _name_ のカラムが索引カラム
103
+ # (Groonga::IndexColumn)であるなら +true+ を返す。
137
104
  def index_column?(name)
138
105
  column(name).index?
139
106
  end
140
107
 
141
- # call-seq:
142
- # record.vector_column?(name) -> true/false
143
- #
144
- # 名前が_name_のカラムの値がベクターであるなら+true+を返す。
108
+ # 名前が _name_ のカラムの値がベクターであるなら +true+ を返す。
145
109
  #
146
110
  # @since: 1.0.5
147
111
  def vector_column?(name)
148
112
  column(name).vector?
149
113
  end
150
114
 
151
- # call-seq:
152
- # record.scalar_column?(name) -> true/false
153
- #
154
- # 名前が_name_のカラムの値がスカラーであるなら+true+を返す。
115
+ # 名前が _name_ のカラムの値がスカラーであるなら +true+ を返す。
155
116
  #
156
117
  # @since: 1.0.5
157
118
  def scalar_column?(name)
158
119
  column(name).scalar?
159
120
  end
160
121
 
161
- # call-seq:
162
- # record.search(name, query, options={}) -> Groonga::Hash
163
- #
164
- # 名前が_name_のGroonga::IndexColumnのsearchメソッドを呼ぶ。
165
- # _query_と_options_はそのメソッドにそのまま渡される。詳しく
122
+ # 名前が _name_ のGroonga::IndexColumnの search メソッドを呼ぶ。
123
+ # _query_ _options_ はそのメソッドにそのまま渡される。詳しく
166
124
  # はGroonga::IndexColumn#searchを参照。
167
125
  def search(name, query, options={})
168
126
  column(name).search(query, options)
169
127
  end
170
128
 
171
- # call-seq:
172
- # record.key -> 主キー
173
- #
174
129
  # レコードの主キーを返す。
175
130
  #
176
- # _record_が所属するテーブルがGroonga:::Arrayの場合は常
177
- # に+nil+を返す。
131
+ # _record_ が所属するテーブルがGroonga:::Arrayの場合は常
132
+ # に +nil+ を返す。
178
133
  def key
179
134
  if support_key?
180
135
  @key ||= @table.key(@id)
@@ -182,13 +137,9 @@ module Groonga
182
137
  nil
183
138
  end
184
139
  end
185
-
186
- # call-seq:
187
- # record.record_id -> IDまたは主キー
188
- #
189
140
  # レコードを一意に識別するための情報を返す。
190
141
  #
191
- # _record_が所属するテーブルがGroonga:::Arrayの場合はID
142
+ # _record_ が所属するテーブルがGroonga:::Arrayの場合はID
192
143
  # を返し、それ以外の場合は主キーを返す。
193
144
  def record_id
194
145
  if support_key?
@@ -198,36 +149,24 @@ module Groonga
198
149
  end
199
150
  end
200
151
 
201
- # call-seq:
202
- # record.record_raw_id -> ID
203
- #
204
152
  # レコードのIDを返す。
205
153
  def record_raw_id
206
154
  @id
207
155
  end
208
156
  alias_method :id, :record_raw_id
209
157
 
210
- # call-seq:
211
- # record.score -> スコア値
212
- #
213
158
  # レコードのスコア値を返す。検索結果として生成されたテーブル
214
159
  # のみに定義される。
215
160
  def score
216
161
  self["_score"]
217
162
  end
218
163
 
219
- # call-seq:
220
- # record.support_score? -> true/false
221
- #
222
- # Groonga::Record#scoreが利用できる場合はtrueを
164
+ # Groonga::Record#scoreが利用できる場合は +true+ を
223
165
  # 返す。
224
166
  def support_score?
225
167
  @table.have_column?("_score") # TODO delegate to Table
226
168
  end
227
169
 
228
- # call-seq:
229
- # record.n_sub_records -> 件数
230
- #
231
170
  # 主キーの値が同一であったレコードの件数を返す。検索結果とし
232
171
  # て生成されたテーブルのみに定義される。
233
172
  #
@@ -237,60 +176,39 @@ module Groonga
237
176
  self["_nsubrecs"]
238
177
  end
239
178
 
240
- # call-seq:
241
- # record.support_sub_records? -> true/false
242
- #
243
- # Groonga::Record#n_sub_recordsが利用できる場合はtrueを
179
+ # Groonga::Record#n_sub_recordsが利用できる場合は +true+ を
244
180
  # 返す。
245
181
  def support_sub_records?
246
182
  @table.support_sub_records?
247
183
  end
248
184
 
249
- # call-seq:
250
- # record.value -> 値
251
- #
252
185
  # レコードの値を返す。
253
186
  def value
254
187
  @table.value(@id, :id => true)
255
188
  end
256
189
 
257
- # call-seq:
258
- # record.value = 値
259
- #
260
190
  # レコードの値を設定する。既存の値は上書きされる。
261
191
  def value=(value)
262
192
  @table.set_value(@id, value, :id => true)
263
193
  end
264
194
 
265
- # call-seq:
266
- # record.increment!(name, delta=nil)
267
- #
268
- # このレコードの_name_で指定されたカラムの値を_delta_だけ増
269
- # 加する。_delta_が+nil+の場合は1増加する。
195
+ # このレコードの _name_ で指定されたカラムの値を _delta_ だけ増
196
+ # 加する。 _delta_ が +nil+ の場合は1増加する。
270
197
  def increment!(name, delta=nil)
271
198
  column(name).increment!(@id, delta)
272
199
  end
273
200
 
274
- # call-seq:
275
- # record.decrement!(name, delta=nil)
276
- #
277
- # このレコードの_name_で指定されたカラムの値を_delta_だけ減
278
- # 少する。_delta_が+nil+の場合は1減少する。
201
+ # このレコードの _name_ で指定されたカラムの値を _delta_ だけ減
202
+ # 少する。 _delta_ が +nil+ の場合は1減少する。
279
203
  def decrement!(name, delta=nil)
280
204
  column(name).decrement!(@id, delta)
281
205
  end
282
206
 
283
- # call-seq:
284
- # record.columns -> Groonga::Columnの配列
285
- #
286
207
  # レコードが所属するテーブルの全てのカラムを返す。
287
208
  def columns
288
209
  @table.columns
289
210
  end
290
211
 
291
- # call-seq:
292
- # attributes -> Hash
293
- #
294
212
  # レコードが所属しているテーブルで定義されているインデックス
295
213
  # 型のカラムでない全カラムを対象とし、カラムの名前をキーとし
296
214
  # たこのレコードのカラムの値のハッシュを返す。
@@ -301,36 +219,26 @@ module Groonga
301
219
  accessor.build
302
220
  end
303
221
 
304
- # call-seq:
305
- # record.delete
306
- #
307
222
  # レコードを削除する。
308
223
  def delete
309
224
  @table.delete(@id)
310
225
  end
311
226
 
312
- # call-seq:
313
- # record.lock(options={})
314
- # record.lock(options={}) {...}
315
- #
316
227
  # レコードが所属するテーブルをロックする。ロックに失敗した場
317
228
  # 合はGroonga::ResourceDeadlockAvoided例外が発生する。
318
229
  #
319
230
  # ブロックを指定した場合はブロックを抜けたときにunlockする。
320
231
  #
321
- # 利用可能なオプションは以下の通り。
322
- #
323
- # [_:timeout_]
324
- # ロックを獲得できなかった場合は_:timeout_秒間ロックの獲
325
- # 得を試みる。_:timeout_秒以内にロックを獲得できなかった
326
- # 場合は例外が発生する。
232
+ # 利用可能な _option_ は以下の通り。
233
+ # @param [Hash] options The name and value
234
+ # pairs. Omitted names are initialized as the default value.
235
+ # @option options [Integer] :timeout The timeout
236
+ # ロックを獲得できなかった場合は _:timeout_ 秒間ロックの獲得を試みる。
237
+ # _:timeout_ 秒以内にロックを獲得できなかった場合は例外が発生する。
327
238
  def lock(options={}, &block)
328
239
  @table.lock(options.merge(:id => @id), &block)
329
240
  end
330
241
 
331
- # call-seq:
332
- # record.unlock(options={})
333
- #
334
242
  # レコードが所属するテーブルのロックを解除する。
335
243
  #
336
244
  # 利用可能なオプションは現在は無い。
@@ -338,9 +246,6 @@ module Groonga
338
246
  @table.unlock(options.merge(:id => @id))
339
247
  end
340
248
 
341
- # call-seq:
342
- # record.clear_lock(options={})
343
- #
344
249
  # レコードが所属するテーブルのロックを強制的に解除する。
345
250
  #
346
251
  # 利用可能なオプションは現在は無い。
@@ -348,25 +253,20 @@ module Groonga
348
253
  @table.clear_lock(options.merge(:id => @id))
349
254
  end
350
255
 
351
- # call-seq:
352
- # record.locked?(options={}) -> true/false
353
- #
354
- # レコードが所属するテーブルがロックされていれば+true+を返す。
256
+ # レコードが所属するテーブルがロックされていれば +true+ を返す。
355
257
  #
356
258
  # 利用可能なオプションは現在は無い。
357
259
  def locked?(options={})
358
260
  @table.locked?(options.merge(:id => @id))
359
261
  end
360
262
 
361
- # call-seq:
362
- # record.valid_id? -> true/false
363
- #
364
- # レコードが持つIDが有効なIDであれば+true+を返す。
263
+ # レコードが持つIDが有効なIDであれば +true+ を返す。
365
264
  def valid_id?
366
265
  @table.exist?(@id)
367
266
  end
368
267
 
369
- def methods(include_inherited=true) # :nodoc:
268
+ # @private
269
+ def methods(include_inherited=true)
370
270
  _methods = super
371
271
  return _methods unless include_inherited
372
272
  columns.each do |column|
@@ -377,7 +277,8 @@ module Groonga
377
277
  _methods
378
278
  end
379
279
 
380
- def respond_to?(name) # :nodoc:
280
+ # @private
281
+ def respond_to?(name)
381
282
  super or !@table.column(name.to_s.sub(/=\z/, '')).nil?
382
283
  end
383
284
 
@@ -395,7 +296,8 @@ module Groonga
395
296
  name.to_s
396
297
  end
397
298
 
398
- def column(name) # :nodoc:
299
+ # @private
300
+ def column(name)
399
301
  _column = @table.column(normalize_column_name(name))
400
302
  raise NoSuchColumn, "column(#{name.inspect}) is nil" if _column.nil?
401
303
  _column
@@ -421,7 +323,8 @@ module Groonga
421
323
  end
422
324
  end
423
325
 
424
- class AttributeHashBuilder # :nodoc:
326
+ # @private
327
+ class AttributeHashBuilder
425
328
  attr_reader :attributes
426
329
 
427
330
  def initialize(root_record)
@@ -510,3 +413,4 @@ module Groonga
510
413
  end
511
414
  end
512
415
  end
416
+