rroonga 1.2.5 → 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +23 -285
- data/ext/groonga/Makefile +1 -1
- data/ext/groonga/extconf.rb +4 -2
- data/ext/groonga/rb-grn-array.c +5 -4
- data/ext/groonga/rb-grn-context.c +7 -22
- data/ext/groonga/rb-grn-database.c +43 -1
- data/ext/groonga/rb-grn-index-column.c +5 -0
- data/ext/groonga/rb-grn-object.c +58 -26
- data/ext/groonga/rb-grn-patricia-trie.c +2 -1
- data/ext/groonga/rb-grn-record.c +11 -1
- data/ext/groonga/rb-grn-table-key-support.c +21 -10
- data/ext/groonga/rb-grn-utils.c +3 -1
- data/ext/groonga/rb-grn-variable-size-column.c +47 -1
- data/ext/groonga/rb-grn.h +4 -1
- data/extconf.rb +1 -0
- data/lib/groonga/pagination.rb +1 -1
- data/lib/groonga/record.rb +10 -0
- data/rroonga-build.rb +1 -1
- data/test/test-accessor.rb +4 -0
- data/test/test-array.rb +9 -1
- data/test/test-database.rb +16 -0
- data/test/test-hash.rb +11 -2
- data/test/test-patricia-trie.rb +10 -1
- data/test/test-table-select.rb +31 -17
- data/test/test-type.rb +3 -3
- data/test/test-variable-size-column.rb +8 -1
- metadata +18 -4
data/Rakefile
CHANGED
@@ -26,6 +26,7 @@ require 'rubygems/package_task'
|
|
26
26
|
require 'yard'
|
27
27
|
require 'jeweler'
|
28
28
|
require 'rake/extensiontask'
|
29
|
+
require 'packnga'
|
29
30
|
|
30
31
|
if YAML.const_defined?(:ENGINE)
|
31
32
|
begin
|
@@ -101,6 +102,28 @@ Gem::PackageTask.new(spec) do |pkg|
|
|
101
102
|
pkg.need_tar_gz = true
|
102
103
|
end
|
103
104
|
|
105
|
+
document_task = Packnga::DocumentTask.new(spec) do |t|
|
106
|
+
t.yard do |yard_task|
|
107
|
+
yard_task.files += FileList["ext/**/*.c"]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
namespace :reference do
|
112
|
+
namespace :publication do
|
113
|
+
task :keep_compatible do
|
114
|
+
File.open(document_task.htaccess, "a") do |file|
|
115
|
+
file.puts("Redirect permanent /#{spec.name}/text/TUTORIAL_ja_rdoc.html " +
|
116
|
+
"#{spec.homepage}#{spec.name}/ja/file.tutorial.html")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
task :generate => :keep_compatible
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
Packnga::ReleaseTask.new(spec) do |task|
|
125
|
+
end
|
126
|
+
|
104
127
|
module YARD
|
105
128
|
module CodeObjects
|
106
129
|
class Proxy
|
@@ -123,33 +146,6 @@ module YARD
|
|
123
146
|
end
|
124
147
|
end
|
125
148
|
|
126
|
-
reference_base_dir = Pathname.new("doc/reference")
|
127
|
-
doc_en_dir = reference_base_dir + "en"
|
128
|
-
html_base_dir = Pathname.new("doc/html")
|
129
|
-
html_reference_dir = html_base_dir + spec.name
|
130
|
-
YARD::Rake::YardocTask.new do |task|
|
131
|
-
task.options += ["--title", spec.name]
|
132
|
-
# task.options += ["--charset", "UTF-8"]
|
133
|
-
task.options += ["--readme", "README.textile"]
|
134
|
-
task.options += ["--files", "doc/text/**/*"]
|
135
|
-
task.options += ["--output-dir", doc_en_dir.to_s]
|
136
|
-
task.options += ["--charset", "utf-8"]
|
137
|
-
task.files += FileList["ext/groonga/**/*.c"]
|
138
|
-
task.files += FileList["lib/**/*.rb"]
|
139
|
-
end
|
140
|
-
|
141
|
-
task :yard do
|
142
|
-
doc_en_dir.find do |path|
|
143
|
-
next if path.extname != ".html"
|
144
|
-
html = path.read
|
145
|
-
html = html.gsub(/<div id="footer">.+<\/div>/m,
|
146
|
-
"<div id=\"footer\"></div>")
|
147
|
-
path.open("w") do |html_file|
|
148
|
-
html_file.print(html)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
149
|
def windows?(platform=nil)
|
154
150
|
platform ||= RUBY_PLATFORM
|
155
151
|
platform =~ /mswin(?!ce)|mingw|cygwin|bccwin/
|
@@ -191,264 +187,6 @@ Rake::ExtensionTask.new("groonga", spec) do |ext|
|
|
191
187
|
end
|
192
188
|
end
|
193
189
|
|
194
|
-
include ERB::Util
|
195
|
-
|
196
|
-
def apply_template(content, paths, templates, language)
|
197
|
-
content = content.sub(/lang="en"/, "lang=\"#{language}\"")
|
198
|
-
|
199
|
-
title = nil
|
200
|
-
content = content.sub(/<title>(.+?)<\/title>/m) do
|
201
|
-
title = $1
|
202
|
-
templates[:head].result(binding)
|
203
|
-
end
|
204
|
-
|
205
|
-
content = content.sub(/<body(?:.*?)>/) do |body_start|
|
206
|
-
"#{body_start}\n#{templates[:header].result(binding)}\n"
|
207
|
-
end
|
208
|
-
|
209
|
-
content = content.sub(/<\/body/) do |body_end|
|
210
|
-
"\n#{templates[:footer].result(binding)}\n#{body_end}"
|
211
|
-
end
|
212
|
-
|
213
|
-
content
|
214
|
-
end
|
215
|
-
|
216
|
-
def erb_template(name)
|
217
|
-
file = File.join("doc/templates", "#{name}.html.erb")
|
218
|
-
template = File.read(file)
|
219
|
-
erb = ERB.new(template, nil, "-")
|
220
|
-
erb.filename = file
|
221
|
-
erb
|
222
|
-
end
|
223
|
-
|
224
|
-
def rsync_to_rubyforge(spec, source, destination, options={})
|
225
|
-
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
226
|
-
host = "#{config["username"]}@rubyforge.org"
|
227
|
-
|
228
|
-
rsync_args = "-av --exclude '*.erb' --chmod=ug+w"
|
229
|
-
rsync_args << " --delete" if options[:delete]
|
230
|
-
remote_dir = "/var/www/gforge-projects/#{spec.rubyforge_project}/"
|
231
|
-
sh("rsync #{rsync_args} #{source} #{host}:#{remote_dir}#{destination}")
|
232
|
-
end
|
233
|
-
|
234
|
-
def rake(*arguments)
|
235
|
-
ruby($0, *arguments)
|
236
|
-
end
|
237
|
-
|
238
|
-
namespace :reference do
|
239
|
-
translate_languages = [:ja]
|
240
|
-
supported_languages = [:en, *translate_languages]
|
241
|
-
html_files = FileList[doc_en_dir + "**/*.html"].to_a
|
242
|
-
|
243
|
-
directory reference_base_dir.to_s
|
244
|
-
CLOBBER.include(reference_base_dir.to_s)
|
245
|
-
|
246
|
-
po_dir = "doc/po"
|
247
|
-
namespace :pot do
|
248
|
-
pot_file = "#{po_dir}/#{spec.name}.pot"
|
249
|
-
|
250
|
-
directory po_dir
|
251
|
-
file pot_file => ["po", *html_files] do |t|
|
252
|
-
sh("xml2po", "--keep-entities", "--output", t.name, *html_files)
|
253
|
-
end
|
254
|
-
|
255
|
-
desc "Generates pot file."
|
256
|
-
task :generate => pot_file
|
257
|
-
end
|
258
|
-
|
259
|
-
namespace :po do
|
260
|
-
translate_languages.each do |language|
|
261
|
-
namespace language do
|
262
|
-
po_file = "#{po_dir}/#{language}.po"
|
263
|
-
|
264
|
-
file po_file => html_files do |t|
|
265
|
-
sh("xml2po", "--keep-entities", "--update", t.name, *html_files)
|
266
|
-
end
|
267
|
-
|
268
|
-
desc "Updates po file for #{language}."
|
269
|
-
task :update => po_file
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
desc "Updates po files."
|
274
|
-
task :update do
|
275
|
-
ruby($0, "clobber")
|
276
|
-
ruby($0, "yard")
|
277
|
-
translate_languages.each do |language|
|
278
|
-
ruby($0, "reference:po:#{language}:update")
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
namespace :translate do
|
284
|
-
translate_languages.each do |language|
|
285
|
-
po_file = "#{po_dir}/#{language}.po"
|
286
|
-
translate_doc_dir = "#{reference_base_dir}/#{language}"
|
287
|
-
|
288
|
-
desc "Translates documents to #{language}."
|
289
|
-
task language => [po_file, reference_base_dir, *html_files] do
|
290
|
-
doc_en_dir.find do |path|
|
291
|
-
base_path = path.relative_path_from(doc_en_dir)
|
292
|
-
translated_path = "#{translate_doc_dir}/#{base_path}"
|
293
|
-
if path.directory?
|
294
|
-
mkdir_p(translated_path)
|
295
|
-
next
|
296
|
-
end
|
297
|
-
case path.extname
|
298
|
-
when ".html"
|
299
|
-
sh("xml2po --keep-entities " +
|
300
|
-
"--po-file #{po_file} --language #{language} " +
|
301
|
-
"#{path} > #{translated_path}")
|
302
|
-
else
|
303
|
-
cp(path.to_s, translated_path, :preserve => true)
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
translate_task_names = translate_languages.collect do |language|
|
311
|
-
"reference:translate:#{language}"
|
312
|
-
end
|
313
|
-
desc "Translates references."
|
314
|
-
task :translate => translate_task_names
|
315
|
-
|
316
|
-
desc "Generates references."
|
317
|
-
task :generate => [:yard, :translate]
|
318
|
-
|
319
|
-
namespace :publication do
|
320
|
-
task :prepare do
|
321
|
-
supported_languages.each do |language|
|
322
|
-
raw_reference_dir = reference_base_dir + language.to_s
|
323
|
-
prepared_reference_dir = html_reference_dir + language.to_s
|
324
|
-
rm_rf(prepared_reference_dir.to_s)
|
325
|
-
head = erb_template("head.#{language}")
|
326
|
-
header = erb_template("header.#{language}")
|
327
|
-
footer = erb_template("footer.#{language}")
|
328
|
-
raw_reference_dir.find do |path|
|
329
|
-
relative_path = path.relative_path_from(raw_reference_dir)
|
330
|
-
prepared_path = prepared_reference_dir + relative_path
|
331
|
-
if path.directory?
|
332
|
-
mkdir_p(prepared_path.to_s)
|
333
|
-
else
|
334
|
-
case path.basename.to_s
|
335
|
-
when /(?:file|method|class)_list\.html\z/
|
336
|
-
cp(path.to_s, prepared_path.to_s)
|
337
|
-
when /\.html\z/
|
338
|
-
relative_dir_path = relative_path.dirname
|
339
|
-
current_path = relative_dir_path + path.basename
|
340
|
-
if current_path.basename.to_s == "index.html"
|
341
|
-
current_path = current_path.dirname
|
342
|
-
end
|
343
|
-
top_path = html_base_dir.relative_path_from(prepared_path.dirname)
|
344
|
-
paths = {
|
345
|
-
:top => top_path,
|
346
|
-
:current => current_path,
|
347
|
-
}
|
348
|
-
templates = {
|
349
|
-
:head => head,
|
350
|
-
:header => header,
|
351
|
-
:footer => footer
|
352
|
-
}
|
353
|
-
content = apply_template(File.read(path.to_s),
|
354
|
-
paths,
|
355
|
-
templates,
|
356
|
-
language)
|
357
|
-
File.open(prepared_path.to_s, "w") do |file|
|
358
|
-
file.print(content)
|
359
|
-
end
|
360
|
-
else
|
361
|
-
cp(path.to_s, prepared_path.to_s)
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
File.open("#{html_reference_dir}/.htaccess", "w") do |file|
|
367
|
-
file.puts("Redirect permanent /#{spec.name}/text/TUTORIAL_ja_rdoc.html " +
|
368
|
-
"#{spec.homepage}#{spec.name}/ja/file.tutorial.html")
|
369
|
-
file.puts("RedirectMatch permanent ^/#{spec.name}/$ " +
|
370
|
-
"#{spec.homepage}#{spec.name}/en/")
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
desc "Upload document to rubyforge."
|
376
|
-
task :publish => [:generate, "reference:publication:prepare"] do
|
377
|
-
rsync_to_rubyforge(spec, "#{html_reference_dir}/", spec.name)
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
namespace :html do
|
382
|
-
desc "Publish HTML to Web site."
|
383
|
-
task :publish do
|
384
|
-
rsync_to_rubyforge(spec, "#{html_base_dir}/", "")
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
desc "Upload document and HTML to rubyforge."
|
389
|
-
task :publish => ["html:publish", "reference:publish"]
|
390
|
-
|
391
|
-
desc "Tag the current revision."
|
392
|
-
task :tag do
|
393
|
-
sh("git tag -a #{version} -m 'release #{version}!!!'")
|
394
|
-
end
|
395
|
-
|
396
|
-
namespace :release do
|
397
|
-
namespace :info do
|
398
|
-
desc "update version in index HTML."
|
399
|
-
task :update do
|
400
|
-
old_version = ENV["OLD_VERSION"]
|
401
|
-
old_release_date = ENV["OLD_RELEASE_DATE"]
|
402
|
-
new_release_date = ENV["RELEASE_DATE"] || Time.now.strftime("%Y-%m-%d")
|
403
|
-
new_version = ENV["VERSION"]
|
404
|
-
|
405
|
-
empty_options = []
|
406
|
-
empty_options << "OLD_VERSION" if old_version.nil?
|
407
|
-
empty_options << "OLD_RELEASE_DATE" if old_release_date.nil?
|
408
|
-
|
409
|
-
unless empty_options.empty?
|
410
|
-
raise ArgumentError, "Specify option(s) of #{empty_options.join(",")}."
|
411
|
-
end
|
412
|
-
|
413
|
-
indexes = ["doc/html/index.html", "doc/html/index.html.ja"]
|
414
|
-
indexes.each do |index|
|
415
|
-
content = replaced_content = File.read(index)
|
416
|
-
[[old_version, new_version],
|
417
|
-
[old_release_date, new_release_date]].each do |old, new|
|
418
|
-
replaced_content = replaced_content.gsub(/#{Regexp.escape(old)}/, new)
|
419
|
-
if /\./ =~ old
|
420
|
-
old_undnerscore = old.gsub(/\./, '-')
|
421
|
-
new_underscore = new.gsub(/\./, '-')
|
422
|
-
replaced_content =
|
423
|
-
replaced_content.gsub(/#{Regexp.escape(old_underscore)}/,
|
424
|
-
new_underscore)
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
next if replaced_content == content
|
429
|
-
File.open(index, "w") do |output|
|
430
|
-
output.print(replaced_content)
|
431
|
-
end
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
namespace :rubyforge do
|
437
|
-
desc "Upload tar.gz to RubyForge."
|
438
|
-
task :upload => "package" do
|
439
|
-
ruby("-S", "rubyforge",
|
440
|
-
"add_release",
|
441
|
-
spec.rubyforge_project,
|
442
|
-
spec.name,
|
443
|
-
spec.version.to_s,
|
444
|
-
"pkg/#{spec.name}-#{spec.version}.tar.gz")
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
desc "Release to RubyForge."
|
449
|
-
task :rubyforge => "release:rubyforge:upload"
|
450
|
-
end
|
451
|
-
|
452
190
|
namespace :test do
|
453
191
|
task :install do
|
454
192
|
gemspec_helper = Rake.application.jeweler.gemspec_helper
|
data/ext/groonga/Makefile
CHANGED
@@ -60,7 +60,7 @@ warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwri
|
|
60
60
|
CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 -fPIC -Wall -I/tmp/local/include/groonga
|
61
61
|
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
62
62
|
DEFS =
|
63
|
-
CPPFLAGS = -DRB_GRN_COMPILATION -DGRN_MAJOR_VERSION=1 -DGRN_MINOR_VERSION=2 -DGRN_MICRO_VERSION=
|
63
|
+
CPPFLAGS = -DRB_GRN_COMPILATION -DGRN_MAJOR_VERSION=1 -DGRN_MINOR_VERSION=2 -DGRN_MICRO_VERSION=5 -DHAVE_RB_ERRINFO -DHAVE_TYPE_ENUM_RUBY_VALUE_TYPE $(DEFS) $(cppflags)
|
64
64
|
CXXFLAGS = $(CFLAGS) -fno-strict-aliasing -g
|
65
65
|
ldflags = -L. -rdynamic -Wl,-export-dynamic -L/tmp/local/lib
|
66
66
|
dldflags =
|
data/ext/groonga/extconf.rb
CHANGED
@@ -158,7 +158,9 @@ checking_for(checking_message("debug flag")) do
|
|
158
158
|
debug
|
159
159
|
end
|
160
160
|
|
161
|
-
|
162
|
-
$INSTALLFILES
|
161
|
+
if ENV["INSTALL_RB"] == "yes"
|
162
|
+
$INSTALLFILES ||= []
|
163
|
+
$INSTALLFILES << ["../../lib/**/*.rb", "$(RUBYLIBDIR)", "../../lib"]
|
164
|
+
end
|
163
165
|
|
164
166
|
create_makefile(module_name)
|
data/ext/groonga/rb-grn-array.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
|
-
Copyright (C) 2009-
|
3
|
+
Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
|
5
5
|
This library is free software; you can redistribute it and/or
|
6
6
|
modify it under the terms of the GNU Lesser General Public
|
@@ -192,10 +192,11 @@ rb_grn_array_add (int argc, VALUE *argv, VALUE self)
|
|
192
192
|
id = grn_table_add(context, table, NULL, 0, NULL);
|
193
193
|
rb_grn_context_check(context, self);
|
194
194
|
|
195
|
-
if (GRN_ID_NIL == id)
|
195
|
+
if (GRN_ID_NIL == id) {
|
196
196
|
return Qnil;
|
197
|
-
else
|
198
|
-
return
|
197
|
+
} else {
|
198
|
+
return rb_grn_record_new_added(self, id, values);
|
199
|
+
}
|
199
200
|
}
|
200
201
|
|
201
202
|
void
|
@@ -59,27 +59,12 @@ rb_grn_context_from_ruby_object (VALUE object)
|
|
59
59
|
return rb_grn_context->context;
|
60
60
|
}
|
61
61
|
|
62
|
-
static void
|
63
|
-
rb_grn_context_unlink_database (grn_ctx *context)
|
64
|
-
{
|
65
|
-
grn_obj *database;
|
66
|
-
|
67
|
-
database = grn_ctx_db(context);
|
68
|
-
debug("context:database: %p:%p\n", context, database);
|
69
|
-
if (database && database->header.type == GRN_DB) {
|
70
|
-
debug("context:database: %p:%p: unlink\n", context, database);
|
71
|
-
grn_obj_unlink(context, database);
|
72
|
-
}
|
73
|
-
debug("context:database: %p:%p: done\n", context, database);
|
74
|
-
}
|
75
|
-
|
76
62
|
void
|
77
63
|
rb_grn_context_fin (grn_ctx *context)
|
78
64
|
{
|
79
65
|
if (context->stat == GRN_CTX_FIN)
|
80
66
|
return;
|
81
67
|
|
82
|
-
rb_grn_context_unlink_database(context);
|
83
68
|
grn_ctx_fin(context);
|
84
69
|
}
|
85
70
|
|
@@ -122,8 +107,6 @@ rb_grn_context_finalizer (grn_ctx *context, int n_args, grn_obj **grn_objects,
|
|
122
107
|
|
123
108
|
rb_grn_context->context = NULL;
|
124
109
|
|
125
|
-
rb_grn_context_unlink_database(context);
|
126
|
-
|
127
110
|
debug("context-finalize: %p:%p:%p: done\n",
|
128
111
|
context, rb_grn_context, rb_grn_context->context);
|
129
112
|
|
@@ -315,7 +298,7 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
|
|
315
298
|
{
|
316
299
|
RbGrnContext *rb_grn_context;
|
317
300
|
grn_ctx *context;
|
318
|
-
int flags =
|
301
|
+
int flags = GRN_CTX_PER_DB;
|
319
302
|
VALUE options, default_options;
|
320
303
|
VALUE rb_encoding;
|
321
304
|
|
@@ -369,10 +352,12 @@ rb_grn_context_close (VALUE self)
|
|
369
352
|
RbGrnContext *rb_grn_context;
|
370
353
|
|
371
354
|
context = SELF(self);
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
355
|
+
if (context) {
|
356
|
+
rc = grn_ctx_fin(context);
|
357
|
+
Data_Get_Struct(self, RbGrnContext, rb_grn_context);
|
358
|
+
rb_grn_context->context = NULL;
|
359
|
+
rb_grn_rc_check(rc, self);
|
360
|
+
}
|
376
361
|
|
377
362
|
return Qnil;
|
378
363
|
}
|
@@ -195,7 +195,7 @@ rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
|
|
195
195
|
grn_obj_unlink(context, old_database);
|
196
196
|
database = grn_db_create(context, path, &create_args);
|
197
197
|
rb_grn_context_check(context, rb_ary_new4(argc, argv));
|
198
|
-
rb_database = GRNOBJECT2RVAL(klass, context, database,
|
198
|
+
rb_database = GRNOBJECT2RVAL(klass, context, database, GRN_FALSE);
|
199
199
|
rb_iv_set(rb_database, "@context", rb_context);
|
200
200
|
if (!NIL_P(rb_context))
|
201
201
|
rb_iv_set(rb_context, "database", rb_database);
|
@@ -504,6 +504,47 @@ rb_grn_database_touch (VALUE self)
|
|
504
504
|
return Qnil;
|
505
505
|
}
|
506
506
|
|
507
|
+
/*
|
508
|
+
* Document-method: defrag
|
509
|
+
*
|
510
|
+
* call-seq:
|
511
|
+
* database.defrag(options={}) -> n_segments
|
512
|
+
*
|
513
|
+
* Defrags all variable size columns in the database.
|
514
|
+
*
|
515
|
+
* @return [Integer] the number of defraged segments
|
516
|
+
* @option options [Integer] :threshold (0) the threshold to
|
517
|
+
* determine whether a segment is defraged. Available
|
518
|
+
* values are -4..22. -4 means all segments are defraged.
|
519
|
+
* 22 means no segment is defraged.
|
520
|
+
* @since 1.2.6
|
521
|
+
*/
|
522
|
+
static VALUE
|
523
|
+
rb_grn_database_defrag (int argc, VALUE *argv, VALUE self)
|
524
|
+
{
|
525
|
+
RbGrnColumn *rb_grn_column;
|
526
|
+
grn_ctx *context;
|
527
|
+
grn_obj *database;
|
528
|
+
int n_segments;
|
529
|
+
VALUE options, rb_threshold;
|
530
|
+
int threshold = 0;
|
531
|
+
|
532
|
+
rb_scan_args(argc, argv, "01", &options);
|
533
|
+
rb_grn_scan_options(options,
|
534
|
+
"threshold", &rb_threshold,
|
535
|
+
NULL);
|
536
|
+
if (!NIL_P(rb_threshold)) {
|
537
|
+
threshold = NUM2INT(rb_threshold);
|
538
|
+
}
|
539
|
+
|
540
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
541
|
+
NULL, NULL, NULL, NULL);
|
542
|
+
n_segments = grn_obj_defrag(context, database, threshold);
|
543
|
+
rb_grn_context_check(context, self);
|
544
|
+
|
545
|
+
return INT2NUM(n_segments);
|
546
|
+
}
|
547
|
+
|
507
548
|
void
|
508
549
|
rb_grn_init_database (VALUE mGrn)
|
509
550
|
{
|
@@ -534,4 +575,5 @@ rb_grn_init_database (VALUE mGrn)
|
|
534
575
|
rb_define_method(rb_cGrnDatabase, "locked?", rb_grn_database_is_locked, 0);
|
535
576
|
|
536
577
|
rb_define_method(rb_cGrnDatabase, "touch", rb_grn_database_touch, 0);
|
578
|
+
rb_define_method(rb_cGrnDatabase, "defrag", rb_grn_database_defrag, -1);
|
537
579
|
}
|
@@ -276,6 +276,7 @@ resolve_source_id (grn_ctx *context, grn_obj *column, grn_id range_id,
|
|
276
276
|
source_id = NUM2UINT(rb_source);
|
277
277
|
} else {
|
278
278
|
grn_obj *source;
|
279
|
+
grn_bool need_source_unlink = GRN_FALSE;
|
279
280
|
|
280
281
|
if (TYPE(rb_source) == T_STRING) {
|
281
282
|
grn_obj *table;
|
@@ -304,6 +305,7 @@ resolve_source_id (grn_ctx *context, grn_obj *column, grn_id range_id,
|
|
304
305
|
name = dot_point + 1;
|
305
306
|
}
|
306
307
|
source = grn_obj_column(context, table, name, length);
|
308
|
+
need_source_unlink = GRN_TRUE;
|
307
309
|
} else {
|
308
310
|
source = RVAL2GRNOBJECT(rb_source, &context);
|
309
311
|
}
|
@@ -321,6 +323,9 @@ resolve_source_id (grn_ctx *context, grn_obj *column, grn_id range_id,
|
|
321
323
|
} else {
|
322
324
|
source_id = grn_obj_id(context, source);
|
323
325
|
}
|
326
|
+
if (need_source_unlink) {
|
327
|
+
grn_obj_unlink(context, source);
|
328
|
+
}
|
324
329
|
}
|
325
330
|
|
326
331
|
return source_id;
|
data/ext/groonga/rb-grn-object.c
CHANGED
@@ -79,19 +79,13 @@ rb_grn_object_from_ruby_object (VALUE object, grn_ctx **context)
|
|
79
79
|
return rb_grn_object->object;
|
80
80
|
}
|
81
81
|
|
82
|
-
static
|
83
|
-
|
84
|
-
|
82
|
+
static void
|
83
|
+
rb_grn_object_run_finalizer (grn_ctx *context, grn_obj *grn_object,
|
84
|
+
RbGrnObject *rb_grn_object)
|
85
85
|
{
|
86
|
-
RbGrnObject *rb_grn_object;
|
87
|
-
grn_obj *grn_object = *grn_objects;
|
88
|
-
|
89
86
|
if (rb_grn_exited)
|
90
|
-
return
|
91
|
-
|
92
|
-
rb_grn_object = user_data->ptr;
|
87
|
+
return;
|
93
88
|
|
94
|
-
grn_obj_user_data(context, grn_object)->ptr = NULL;
|
95
89
|
grn_obj_set_finalizer(context, grn_object, NULL);
|
96
90
|
|
97
91
|
debug("finalize: %p:%p:%p:%p:%p 0x%x\n",
|
@@ -101,11 +95,10 @@ rb_grn_object_finalizer (grn_ctx *context, int n_args, grn_obj **grn_objects,
|
|
101
95
|
|
102
96
|
rb_grn_object->context = NULL;
|
103
97
|
rb_grn_object->object = NULL;
|
98
|
+
rb_grn_object->have_finalizer = GRN_FALSE;
|
104
99
|
|
105
100
|
switch (grn_object->header.type) {
|
106
101
|
case GRN_DB:
|
107
|
-
grn_ctx_use(context, NULL);
|
108
|
-
break;
|
109
102
|
case GRN_TYPE:
|
110
103
|
case GRN_PROC:
|
111
104
|
case GRN_CURSOR_TABLE_HASH_KEY:
|
@@ -148,6 +141,22 @@ rb_grn_object_finalizer (grn_ctx *context, int n_args, grn_obj **grn_objects,
|
|
148
141
|
grn_object->header.type);
|
149
142
|
break;
|
150
143
|
}
|
144
|
+
}
|
145
|
+
|
146
|
+
static grn_obj *
|
147
|
+
rb_grn_object_finalizer (grn_ctx *context, int n_args, grn_obj **grn_objects,
|
148
|
+
grn_user_data *user_data)
|
149
|
+
{
|
150
|
+
RbGrnObject *rb_grn_object;
|
151
|
+
grn_obj *grn_object = *grn_objects;
|
152
|
+
|
153
|
+
if (rb_grn_exited)
|
154
|
+
return NULL;
|
155
|
+
|
156
|
+
rb_grn_object = user_data->ptr;
|
157
|
+
|
158
|
+
grn_obj_user_data(context, grn_object)->ptr = NULL;
|
159
|
+
rb_grn_object_run_finalizer(context, grn_object, rb_grn_object);
|
151
160
|
|
152
161
|
return NULL;
|
153
162
|
}
|
@@ -160,19 +169,26 @@ rb_grn_object_free (RbGrnObject *rb_grn_object)
|
|
160
169
|
|
161
170
|
context = rb_grn_object->context;
|
162
171
|
grn_object = rb_grn_object->object;
|
163
|
-
debug("rb-free: %p:%p:%p; %d\n", context, grn_object, rb_grn_object,
|
164
|
-
rb_grn_object->have_finalizer);
|
165
|
-
if (!rb_grn_exited && context && grn_object &&
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
172
|
+
debug("rb-free: %p:%p:%p; %d:%d\n", context, grn_object, rb_grn_object,
|
173
|
+
rb_grn_object->have_finalizer, rb_grn_object->need_close);
|
174
|
+
if (!rb_grn_exited && context && grn_object &&
|
175
|
+
(rb_grn_object->have_finalizer || rb_grn_object->need_close)) {
|
176
|
+
grn_user_data *user_data = NULL;
|
177
|
+
|
178
|
+
if (rb_grn_object->have_finalizer) {
|
179
|
+
user_data = grn_obj_user_data(context, grn_object);
|
180
|
+
}
|
181
|
+
debug("type: %#x; need_close: %d; user_data: %p; ptr: %p\n",
|
170
182
|
grn_object->header.type,
|
171
183
|
rb_grn_object->need_close,
|
172
184
|
user_data,
|
173
185
|
user_data ? user_data->ptr : NULL);
|
174
|
-
if (
|
175
|
-
|
186
|
+
if (rb_grn_object->have_finalizer) {
|
187
|
+
if (user_data && user_data->ptr) {
|
188
|
+
rb_grn_object_finalizer(context, 1, &grn_object, user_data);
|
189
|
+
} else {
|
190
|
+
rb_grn_object_run_finalizer(context, grn_object, rb_grn_object);
|
191
|
+
}
|
176
192
|
}
|
177
193
|
if (rb_grn_object->need_close) {
|
178
194
|
grn_obj_unlink(context, grn_object);
|
@@ -297,15 +313,21 @@ rb_grn_object_bind_common (VALUE klass, VALUE self, VALUE rb_context,
|
|
297
313
|
|
298
314
|
user_data = grn_obj_user_data(context, object);
|
299
315
|
if (user_data) {
|
300
|
-
debug("set-finalizer: %p:%p:%p
|
316
|
+
debug("set-finalizer: %p:%p:%p %#x\n",
|
301
317
|
context, object, rb_grn_object,
|
302
318
|
object->header.type);
|
303
319
|
user_data->ptr = rb_grn_object;
|
304
320
|
grn_obj_set_finalizer(context, object, rb_grn_object_finalizer);
|
305
321
|
rb_grn_object->have_finalizer = GRN_TRUE;
|
322
|
+
} else if (object->header.type == GRN_ACCESSOR) {
|
323
|
+
debug("set-finalizer(implicit): %p:%p:%p %#x\n",
|
324
|
+
context, object, rb_grn_object,
|
325
|
+
object->header.type);
|
326
|
+
rb_grn_object->have_finalizer = GRN_TRUE;
|
306
327
|
}
|
307
328
|
|
308
329
|
switch (object->header.type) {
|
330
|
+
case GRN_DB:
|
309
331
|
case GRN_PROC:
|
310
332
|
case GRN_TYPE:
|
311
333
|
rb_grn_object->need_close = GRN_FALSE;
|
@@ -495,13 +517,17 @@ rb_grn_object_deconstruct (RbGrnObject *rb_grn_object,
|
|
495
517
|
VALUE
|
496
518
|
rb_grn_object_close (VALUE self)
|
497
519
|
{
|
520
|
+
RbGrnObject *rb_grn_object;
|
498
521
|
grn_obj *object;
|
499
522
|
grn_ctx *context;
|
500
523
|
|
501
|
-
|
524
|
+
rb_grn_object = SELF(self);
|
525
|
+
rb_grn_object_deconstruct(rb_grn_object, &object, &context,
|
502
526
|
NULL, NULL, NULL, NULL);
|
503
|
-
if (object && context)
|
527
|
+
if (object && context) {
|
528
|
+
rb_grn_object_run_finalizer(context, object, rb_grn_object);
|
504
529
|
grn_obj_close(context, object);
|
530
|
+
}
|
505
531
|
|
506
532
|
return Qnil;
|
507
533
|
}
|
@@ -517,13 +543,19 @@ rb_grn_object_close (VALUE self)
|
|
517
543
|
VALUE
|
518
544
|
rb_grn_object_unlink (VALUE self)
|
519
545
|
{
|
546
|
+
RbGrnObject *rb_grn_object;
|
520
547
|
grn_obj *object;
|
521
548
|
grn_ctx *context;
|
522
549
|
|
523
|
-
|
550
|
+
rb_grn_object = SELF(self);
|
551
|
+
rb_grn_object_deconstruct(rb_grn_object, &object, &context,
|
524
552
|
NULL, NULL, NULL, NULL);
|
525
|
-
if (object && context)
|
553
|
+
if (object && context) {
|
554
|
+
if (!(rb_grn_object->object->header.flags & GRN_OBJ_PERSISTENT)) {
|
555
|
+
rb_grn_object_run_finalizer(context, object, rb_grn_object);
|
556
|
+
}
|
526
557
|
grn_obj_unlink(context, object);
|
558
|
+
}
|
527
559
|
|
528
560
|
return Qnil;
|
529
561
|
}
|
@@ -798,6 +798,7 @@ rb_grn_patricia_trie_open_grn_near_cursor (int argc, VALUE *argv, VALUE self,
|
|
798
798
|
GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain);
|
799
799
|
if (key_p->header.domain != table->header.domain) {
|
800
800
|
grn_obj_cast(*context, key_p, &casted_key, 0);
|
801
|
+
grn_obj_unlink(*context, key_p);
|
801
802
|
key_p = &casted_key;
|
802
803
|
}
|
803
804
|
|
@@ -862,7 +863,7 @@ rb_grn_patricia_trie_open_near_cursor (int argc, VALUE *argv, VALUE self)
|
|
862
863
|
VALUE rb_cursor;
|
863
864
|
|
864
865
|
cursor = rb_grn_patricia_trie_open_grn_near_cursor(argc, argv,
|
865
|
-
|
866
|
+
self, &context, GRN_CURSOR_RK);
|
866
867
|
rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
|
867
868
|
rb_iv_set(rb_cursor, "@table", self); /* FIXME: cursor should mark table */
|
868
869
|
if (rb_block_given_p())
|
data/ext/groonga/rb-grn-record.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
|
-
Copyright (C) 2009-
|
3
|
+
Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
|
5
5
|
This library is free software; you can redistribute it and/or
|
6
6
|
modify it under the terms of the GNU Lesser General Public
|
@@ -26,6 +26,16 @@ rb_grn_record_new (VALUE table, grn_id id, VALUE values)
|
|
26
26
|
return rb_grn_record_new_raw(table, UINT2NUM(id), values);
|
27
27
|
}
|
28
28
|
|
29
|
+
VALUE
|
30
|
+
rb_grn_record_new_added (VALUE table, grn_id id, VALUE values)
|
31
|
+
{
|
32
|
+
VALUE record;
|
33
|
+
|
34
|
+
record = rb_grn_record_new(table, id, values);
|
35
|
+
rb_funcall(record, rb_intern("added="), 1, Qtrue);
|
36
|
+
return record;
|
37
|
+
}
|
38
|
+
|
29
39
|
VALUE
|
30
40
|
rb_grn_record_new_raw (VALUE table, VALUE rb_id, VALUE values)
|
31
41
|
{
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
|
-
Copyright (C) 2009-
|
3
|
+
Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
|
5
5
|
This library is free software; you can redistribute it and/or
|
6
6
|
modify it under the terms of the GNU Lesser General Public
|
@@ -88,7 +88,7 @@ rb_grn_table_key_support_bind (RbGrnTableKeySupport *rb_grn_table_key_support,
|
|
88
88
|
}
|
89
89
|
|
90
90
|
static grn_id
|
91
|
-
rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key)
|
91
|
+
rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key, int *added)
|
92
92
|
{
|
93
93
|
grn_ctx *context;
|
94
94
|
grn_obj *table;
|
@@ -103,7 +103,7 @@ rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key)
|
|
103
103
|
GRN_BULK_REWIND(key);
|
104
104
|
RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
|
105
105
|
id = grn_table_add(context, table,
|
106
|
-
GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key),
|
106
|
+
GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key), added);
|
107
107
|
rb_grn_context_check(context, self);
|
108
108
|
|
109
109
|
return id;
|
@@ -116,6 +116,11 @@ rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key)
|
|
116
116
|
* 主キーが_key_のレコード追加し、追加したレコードを返す。レ
|
117
117
|
* コードの追加に失敗した場合は+nil+を返す。
|
118
118
|
*
|
119
|
+
* すでに同じキーのレコードが存在する場合は追加せずに同じレ
|
120
|
+
* コードを返す。追加されたかどうかは
|
121
|
+
* +Groonga::Record#added?+で調べることができる。+true+を返
|
122
|
+
* したら追加されたということを示す。
|
123
|
+
*
|
119
124
|
* _values_にはレコードのカラムに設定する値を指定する。省略
|
120
125
|
* した場合または+nil+を指定した場合はカラムは設定しない。カ
|
121
126
|
* ラムの値は<tt>{:カラム名1 => 値1, :カラム名2 => 値2,
|
@@ -126,13 +131,19 @@ rb_grn_table_key_support_add (int argc, VALUE *argv, VALUE self)
|
|
126
131
|
{
|
127
132
|
grn_id id;
|
128
133
|
VALUE key, values;
|
134
|
+
int added = GRN_FALSE;
|
129
135
|
|
130
136
|
rb_scan_args(argc, argv, "11", &key, &values);
|
131
|
-
id = rb_grn_table_key_support_add_raw(self, key);
|
132
|
-
if (GRN_ID_NIL == id)
|
137
|
+
id = rb_grn_table_key_support_add_raw(self, key, &added);
|
138
|
+
if (GRN_ID_NIL == id) {
|
133
139
|
return Qnil;
|
134
|
-
else
|
135
|
-
|
140
|
+
} else {
|
141
|
+
if (added) {
|
142
|
+
return rb_grn_record_new_added(self, id, values);
|
143
|
+
} else {
|
144
|
+
return rb_grn_record_new(self, id, values);
|
145
|
+
}
|
146
|
+
}
|
136
147
|
}
|
137
148
|
|
138
149
|
grn_id
|
@@ -364,7 +375,7 @@ rb_grn_table_key_support_array_set (VALUE self, VALUE rb_key, VALUE rb_values)
|
|
364
375
|
NULL, NULL, NULL,
|
365
376
|
NULL);
|
366
377
|
|
367
|
-
id = rb_grn_table_key_support_add_raw(self, rb_key);
|
378
|
+
id = rb_grn_table_key_support_add_raw(self, rb_key, NULL);
|
368
379
|
|
369
380
|
if (id == GRN_ID_NIL) {
|
370
381
|
rb_raise(rb_eGrnError,
|
@@ -409,7 +420,7 @@ rb_grn_table_key_support_set_column_value (int argc, VALUE *argv, VALUE self)
|
|
409
420
|
}
|
410
421
|
|
411
422
|
rb_key = rb_id_or_key;
|
412
|
-
id = rb_grn_table_key_support_add_raw(self, rb_key);
|
423
|
+
id = rb_grn_table_key_support_add_raw(self, rb_key, NULL);
|
413
424
|
if (id == GRN_ID_NIL) {
|
414
425
|
rb_raise(rb_eGrnError,
|
415
426
|
"failed to add record: %s",
|
@@ -533,7 +544,7 @@ rb_grn_table_key_support_set_value_by_key (VALUE self,
|
|
533
544
|
&value, NULL, NULL,
|
534
545
|
NULL);
|
535
546
|
|
536
|
-
id = rb_grn_table_key_support_add_raw(self, rb_key);
|
547
|
+
id = rb_grn_table_key_support_add_raw(self, rb_key, NULL);
|
537
548
|
if (GRN_ID_NIL == id) {
|
538
549
|
rb_raise(rb_eGrnError,
|
539
550
|
"failed to add new record with key: <%s>: <%s>",
|
data/ext/groonga/rb-grn-utils.c
CHANGED
@@ -243,6 +243,8 @@ rb_grn_bulk_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *bulk)
|
|
243
243
|
case T_NIL:
|
244
244
|
grn_obj_reinit(context, bulk, GRN_DB_VOID, 0);
|
245
245
|
break;
|
246
|
+
case T_SYMBOL:
|
247
|
+
object = rb_sym_to_s(object);
|
246
248
|
case T_STRING:
|
247
249
|
grn_obj_reinit(context, bulk, GRN_DB_TEXT, 0);
|
248
250
|
rb_grn_context_text_set(context, bulk, object);
|
@@ -306,7 +308,7 @@ rb_grn_bulk_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *bulk)
|
|
306
308
|
} else {
|
307
309
|
rb_raise(rb_eTypeError,
|
308
310
|
"bulked object should be one of "
|
309
|
-
"[nil, true, false, String, Integer, Float, Time, "
|
311
|
+
"[nil, true, false, String, Symbol, Integer, Float, Time, "
|
310
312
|
"Groonga::Object, Groonga::Record]: %s",
|
311
313
|
rb_grn_inspect(object));
|
312
314
|
}
|
@@ -18,7 +18,7 @@
|
|
18
18
|
|
19
19
|
#include "rb-grn.h"
|
20
20
|
|
21
|
-
#define SELF(object) ((
|
21
|
+
#define SELF(object) ((RbGrnColumn *)DATA_PTR(object))
|
22
22
|
|
23
23
|
VALUE rb_cGrnVariableSizeColumn;
|
24
24
|
|
@@ -28,9 +28,55 @@ VALUE rb_cGrnVariableSizeColumn;
|
|
28
28
|
* 可変長データ用のカラム。
|
29
29
|
*/
|
30
30
|
|
31
|
+
/*
|
32
|
+
* Document-method: defrag
|
33
|
+
*
|
34
|
+
* call-seq:
|
35
|
+
* column.defrag(options={}) -> n_segments
|
36
|
+
*
|
37
|
+
* Defrags the column.
|
38
|
+
*
|
39
|
+
* @return [Integer] the number of defraged segments
|
40
|
+
* @option options [Integer] :threshold (0) the threshold to
|
41
|
+
* determine whether a segment is defraged. Available
|
42
|
+
* values are -4..22. -4 means all segments are defraged.
|
43
|
+
* 22 means no segment is defraged.
|
44
|
+
* @since 1.2.6
|
45
|
+
*/
|
46
|
+
static VALUE
|
47
|
+
rb_grn_variable_size_column_defrag (int argc, VALUE *argv, VALUE self)
|
48
|
+
{
|
49
|
+
RbGrnColumn *rb_grn_column;
|
50
|
+
grn_ctx *context = NULL;
|
51
|
+
grn_obj *column;
|
52
|
+
int n_segments;
|
53
|
+
VALUE options, rb_threshold;
|
54
|
+
int threshold = 0;
|
55
|
+
|
56
|
+
rb_scan_args(argc, argv, "01", &options);
|
57
|
+
rb_grn_scan_options(options,
|
58
|
+
"threshold", &rb_threshold,
|
59
|
+
NULL);
|
60
|
+
if (!NIL_P(rb_threshold)) {
|
61
|
+
threshold = NUM2INT(rb_threshold);
|
62
|
+
}
|
63
|
+
|
64
|
+
rb_grn_column = SELF(self);
|
65
|
+
rb_grn_object_deconstruct(RB_GRN_OBJECT(rb_grn_column), &column, &context,
|
66
|
+
NULL, NULL,
|
67
|
+
NULL, NULL);
|
68
|
+
n_segments = grn_obj_defrag(context, column, threshold);
|
69
|
+
rb_grn_context_check(context, self);
|
70
|
+
|
71
|
+
return INT2NUM(n_segments);
|
72
|
+
}
|
73
|
+
|
31
74
|
void
|
32
75
|
rb_grn_init_variable_size_column (VALUE mGrn)
|
33
76
|
{
|
34
77
|
rb_cGrnVariableSizeColumn =
|
35
78
|
rb_define_class_under(mGrn, "VariableSizeColumn", rb_cGrnColumn);
|
79
|
+
|
80
|
+
rb_define_method(rb_cGrnVariableSizeColumn, "defrag",
|
81
|
+
rb_grn_variable_size_column_defrag, -1);
|
36
82
|
}
|
data/ext/groonga/rb-grn.h
CHANGED
@@ -69,7 +69,7 @@ RB_GRN_BEGIN_DECLS
|
|
69
69
|
|
70
70
|
#define RB_GRN_MAJOR_VERSION 1
|
71
71
|
#define RB_GRN_MINOR_VERSION 2
|
72
|
-
#define RB_GRN_MICRO_VERSION
|
72
|
+
#define RB_GRN_MICRO_VERSION 6
|
73
73
|
|
74
74
|
#define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
|
75
75
|
|
@@ -474,6 +474,9 @@ VALUE rb_grn_posting_new (grn_posting *posting,
|
|
474
474
|
VALUE rb_grn_record_new (VALUE table,
|
475
475
|
grn_id id,
|
476
476
|
VALUE values);
|
477
|
+
VALUE rb_grn_record_new_added (VALUE table,
|
478
|
+
grn_id id,
|
479
|
+
VALUE values);
|
477
480
|
VALUE rb_grn_record_new_raw (VALUE table,
|
478
481
|
VALUE id,
|
479
482
|
VALUE values);
|
data/extconf.rb
CHANGED
@@ -34,6 +34,7 @@ Dir.chdir(source_ext_dir.to_s) do
|
|
34
34
|
end
|
35
35
|
ruby = "#{config['bindir']}/#{config['ruby_install_name']}#{config['EXEEXT']}"
|
36
36
|
message("checking in #{ext_dir}...\n")
|
37
|
+
ENV["INSTALL_RB"] = "yes"
|
37
38
|
system(ruby, (ext_dir + 'extconf.rb').to_s, *ARGV) or exit 1
|
38
39
|
message("checking in #{ext_dir}: done.\n")
|
39
40
|
File.open("Makefile") do |file|
|
data/lib/groonga/pagination.rb
CHANGED
@@ -78,7 +78,7 @@ module Groonga
|
|
78
78
|
# selected_entries = entries.select do |record|
|
79
79
|
# entry.description =~ query
|
80
80
|
# end
|
81
|
-
# paged_entries = selected_entries.paginate(["_score", :desc],
|
81
|
+
# paged_entries = selected_entries.paginate([["_score", :desc]],
|
82
82
|
# :page => 1,
|
83
83
|
# :size => 10)
|
84
84
|
#
|
data/lib/groonga/record.rb
CHANGED
@@ -32,6 +32,7 @@ module Groonga
|
|
32
32
|
def initialize(table, id, values=nil)
|
33
33
|
@table = table
|
34
34
|
@id = id
|
35
|
+
@added = false
|
35
36
|
if values
|
36
37
|
values.each do |name, value|
|
37
38
|
self[name] = value
|
@@ -380,6 +381,15 @@ module Groonga
|
|
380
381
|
super or !@table.column(name.to_s.sub(/=\z/, '')).nil?
|
381
382
|
end
|
382
383
|
|
384
|
+
def added?
|
385
|
+
@added
|
386
|
+
end
|
387
|
+
|
388
|
+
# @private
|
389
|
+
def added=(added)
|
390
|
+
@added = added
|
391
|
+
end
|
392
|
+
|
383
393
|
private
|
384
394
|
def normalize_column_name(name)
|
385
395
|
name.to_s
|
data/rroonga-build.rb
CHANGED
data/test/test-accessor.rb
CHANGED
data/test/test-array.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009-
|
1
|
+
# Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -91,4 +91,12 @@ class ArrayTest < Test::Unit::TestCase
|
|
91
91
|
users.set_column_value(morita_id, "name", "morita")
|
92
92
|
assert_equal("morita", users.column_value(morita_id, "name"))
|
93
93
|
end
|
94
|
+
|
95
|
+
def test_added?
|
96
|
+
users = Groonga::Array.create(:name => "Users")
|
97
|
+
first_user = users.add
|
98
|
+
assert_predicate(first_user, :added?)
|
99
|
+
second_user = users.add
|
100
|
+
assert_predicate(second_user, :added?)
|
101
|
+
end
|
94
102
|
end
|
data/test/test-database.rb
CHANGED
@@ -130,4 +130,20 @@ class DatabaseTest < Test::Unit::TestCase
|
|
130
130
|
database.touch
|
131
131
|
end
|
132
132
|
end
|
133
|
+
|
134
|
+
def test_defrag
|
135
|
+
setup_database
|
136
|
+
Groonga::Schema.define do |schema|
|
137
|
+
schema.create_table("Users") do |table|
|
138
|
+
table.short_text("name")
|
139
|
+
table.short_text("address")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
users = context["Users"]
|
143
|
+
1000.times do |i|
|
144
|
+
users.add(:name => "user #{i}" * 1000,
|
145
|
+
:address => "address #{i}" * 1000)
|
146
|
+
end
|
147
|
+
assert_equal(7, @database.defrag)
|
148
|
+
end
|
133
149
|
end
|
data/test/test-hash.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
#
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
3
4
|
#
|
4
5
|
# This library is free software; you can redistribute it and/or
|
5
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -75,7 +76,6 @@ class HashTest < Test::Unit::TestCase
|
|
75
76
|
assert_equal(bookmark, bookmarks["http://google.com/"])
|
76
77
|
end
|
77
78
|
|
78
|
-
|
79
79
|
def test_inspect_anonymous
|
80
80
|
path = @tables_dir + "anoymous.groonga"
|
81
81
|
anonymous_table = Groonga::Hash.create(:path => path.to_s)
|
@@ -308,4 +308,13 @@ class HashTest < Test::Unit::TestCase
|
|
308
308
|
}
|
309
309
|
end
|
310
310
|
end
|
311
|
+
|
312
|
+
def test_added?
|
313
|
+
users = Groonga::Hash.create(:name => "Users",
|
314
|
+
:key_type => "ShortText")
|
315
|
+
bob = users.add("bob")
|
316
|
+
assert_predicate(bob, :added?)
|
317
|
+
bob_again = users.add("bob")
|
318
|
+
assert_not_predicate(bob_again, :added?)
|
319
|
+
end
|
311
320
|
end
|
data/test/test-patricia-trie.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2009-
|
3
|
+
# Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -379,4 +379,13 @@ class PatriciaTrieTest < Test::Unit::TestCase
|
|
379
379
|
numbers.add(7)
|
380
380
|
assert_equal([1, 2, 5, 7], numbers.collect {|number| number.key})
|
381
381
|
end
|
382
|
+
|
383
|
+
def test_added?
|
384
|
+
users = Groonga::PatriciaTrie.create(:name => "Users",
|
385
|
+
:key_type => "ShortText")
|
386
|
+
bob = users.add("bob")
|
387
|
+
assert_predicate(bob, :added?)
|
388
|
+
bob_again = users.add("bob")
|
389
|
+
assert_not_predicate(bob_again, :added?)
|
390
|
+
end
|
382
391
|
end
|
data/test/test-table-select.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2009-
|
3
|
+
# Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -53,7 +53,7 @@ class TableSelectTest < Test::Unit::TestCase
|
|
53
53
|
:user => "darashi")
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
56
|
+
def test_sub_expression
|
57
57
|
result = @comments.select do |record|
|
58
58
|
record.match("Hello", "content") &
|
59
59
|
(record["created_at"] < Time.parse("2009-08-01"))
|
@@ -61,22 +61,22 @@ class TableSelectTest < Test::Unit::TestCase
|
|
61
61
|
assert_equal_select_result([@comment2], result)
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
64
|
+
def test_query
|
65
65
|
result = @comments.select("content:@Hello")
|
66
66
|
assert_equal_select_result([@comment1, @comment2], result)
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
69
|
+
def test_query_with_parser
|
70
70
|
result = @comments.select("content @ \"Hello\"", :syntax => :script)
|
71
71
|
assert_equal_select_result([@comment1, @comment2], result)
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
74
|
+
def test_query_with_default_column
|
75
75
|
result = @comments.select("Hello", {:default_column => 'content'})
|
76
76
|
assert_equal_select_result([@comment1, @comment2], result)
|
77
77
|
end
|
78
78
|
|
79
|
-
def
|
79
|
+
def test_expression
|
80
80
|
expression = Groonga::Expression.new
|
81
81
|
variable = expression.define_variable(:domain => @comments)
|
82
82
|
expression.append_object(variable)
|
@@ -87,76 +87,90 @@ class TableSelectTest < Test::Unit::TestCase
|
|
87
87
|
assert_equal_select_result([@comment1, @comment2], result)
|
88
88
|
end
|
89
89
|
|
90
|
-
def
|
90
|
+
def test_query_with_block
|
91
91
|
result = @comments.select("content:@Hello") do |record|
|
92
92
|
record["created_at"] < Time.parse("2009-08-01")
|
93
93
|
end
|
94
94
|
assert_equal_select_result([@comment2], result)
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def test_query_with_block_match
|
98
98
|
result = @comments.select("content:@Hello") do |record|
|
99
99
|
record.match("World", "content")
|
100
100
|
end
|
101
101
|
assert_equal_select_result([@comment2], result)
|
102
102
|
end
|
103
103
|
|
104
|
-
def
|
104
|
+
def test_without_block
|
105
105
|
assert_equal_select_result([@comment1, @comment2,
|
106
106
|
@comment3, @japanese_comment],
|
107
107
|
@comments.select)
|
108
108
|
end
|
109
109
|
|
110
|
-
def
|
110
|
+
def test_query_japanese
|
111
111
|
result = @comments.select("content:@ボロTV")
|
112
112
|
assert_equal_select_result([@japanese_comment], result)
|
113
113
|
end
|
114
114
|
|
115
|
-
def
|
115
|
+
def test_but_query
|
116
116
|
result = @comments.select do |record|
|
117
117
|
record["content"].match "Hello -World"
|
118
118
|
end
|
119
119
|
assert_equal_select_result([@comment1], result)
|
120
120
|
end
|
121
121
|
|
122
|
-
def
|
122
|
+
def test_query_with_three_terms
|
123
123
|
result = @comments.select do |record|
|
124
124
|
record["content"].match "Say Hello World"
|
125
125
|
end
|
126
126
|
assert_equal_select_result([], result)
|
127
127
|
end
|
128
128
|
|
129
|
-
def
|
129
|
+
def test_query_with_brackets
|
130
130
|
result = @comments.select do |record|
|
131
131
|
record["content"].match "Say (Hello World)"
|
132
132
|
end
|
133
133
|
assert_equal_select_result([], result)
|
134
134
|
end
|
135
135
|
|
136
|
-
def
|
136
|
+
def test_equal_reference_column_by_key
|
137
137
|
result = @comments.select do |record|
|
138
138
|
record["user"] == "darashi"
|
139
139
|
end
|
140
140
|
assert_equal_select_result([@japanese_comment], result)
|
141
141
|
end
|
142
142
|
|
143
|
-
def
|
143
|
+
def test_not_equal_reference_column_by_key
|
144
144
|
result = @comments.select('user != "darashi"', :syntax => :script)
|
145
145
|
assert_equal_select_result([@comment1, @comment2, @comment3],
|
146
146
|
result)
|
147
147
|
end
|
148
148
|
|
149
|
-
def
|
149
|
+
def test_equal_reference_column_by_nonexistent_key
|
150
150
|
result = @comments.select do |record|
|
151
151
|
record["user"] == "nonexistent"
|
152
152
|
end
|
153
153
|
assert_equal_select_result([], result)
|
154
154
|
end
|
155
155
|
|
156
|
-
def
|
156
|
+
def test_query_key
|
157
157
|
result = @users.select do |record|
|
158
158
|
record["_key"] =~ "mori"
|
159
159
|
end
|
160
160
|
assert_equal_select_result([@users["morita"]], result)
|
161
161
|
end
|
162
|
+
|
163
|
+
def test_symbol
|
164
|
+
result = @comments.select do |record|
|
165
|
+
record[:content].match("Say Hello World")
|
166
|
+
end
|
167
|
+
assert_equal_select_result([], result)
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_method
|
171
|
+
result = @comments.select do |record|
|
172
|
+
record.content.match("Say Hello World")
|
173
|
+
end
|
174
|
+
assert_equal_select_result([], result)
|
175
|
+
end
|
162
176
|
end
|
data/test/test-type.rb
CHANGED
@@ -23,12 +23,12 @@ class TypeTest < Test::Unit::TestCase
|
|
23
23
|
assert_equal("user_id", type.name)
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def test_new_with_space_name
|
27
27
|
exception = assert_raise(Groonga::InvalidArgument) do
|
28
|
-
Groonga::Type.new("user
|
28
|
+
Groonga::Type.new("user id", :type => :integer)
|
29
29
|
end
|
30
30
|
message =
|
31
|
-
"name can't start with '_' and
|
31
|
+
"name can't start with '_' and contains only 0-9, A-Z, a-z, #, - or _"
|
32
32
|
assert_match(/#{Regexp.escape(message)}/,
|
33
33
|
exception.message)
|
34
34
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
|
1
|
+
# Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -107,4 +107,11 @@ class VariableSizeColumnTest < Test::Unit::TestCase
|
|
107
107
|
@morita.prepend("nick_names", "moritapo")
|
108
108
|
assert_equal(["moritapo", "morita"], @morita["nick_names"])
|
109
109
|
end
|
110
|
+
|
111
|
+
def test_defrag
|
112
|
+
1000.times do |i|
|
113
|
+
@users.add(:name => "user #{i}" * 1000)
|
114
|
+
end
|
115
|
+
assert_equal(3, @name.defrag)
|
116
|
+
end
|
110
117
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rroonga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
9
|
+
- 6
|
10
|
+
version: 1.2.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kouhei Sutou
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2011-08-
|
22
|
+
date: 2011-08-28 00:00:00 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -119,6 +119,20 @@ dependencies:
|
|
119
119
|
prerelease: false
|
120
120
|
type: :development
|
121
121
|
requirement: *id007
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
name: packnga
|
133
|
+
prerelease: false
|
134
|
+
type: :development
|
135
|
+
requirement: *id008
|
122
136
|
description: |-
|
123
137
|
rroonga is an extension library to use groonga's DB-API
|
124
138
|
layer. rroonga provides Rubyish readable and writable API
|