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 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
@@ -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=1 -DHAVE_RB_ERRINFO -DHAVE_TYPE_ENUM_RUBY_VALUE_TYPE $(DEFS) $(cppflags)
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 =
@@ -158,7 +158,9 @@ checking_for(checking_message("debug flag")) do
158
158
  debug
159
159
  end
160
160
 
161
- $INSTALLFILES ||= []
162
- $INSTALLFILES << ["../../lib/**/*.rb", "$(RUBYLIBDIR)", "../../lib"]
161
+ if ENV["INSTALL_RB"] == "yes"
162
+ $INSTALLFILES ||= []
163
+ $INSTALLFILES << ["../../lib/**/*.rb", "$(RUBYLIBDIR)", "../../lib"]
164
+ end
163
165
 
164
166
  create_makefile(module_name)
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
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 rb_grn_record_new(self, id, values);
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 = 0;
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
- rc = grn_ctx_fin(context);
373
- Data_Get_Struct(self, RbGrnContext, rb_grn_context);
374
- rb_grn_context->context = NULL;
375
- rb_grn_rc_check(rc, self);
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, GRN_TRUE);
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;
@@ -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 grn_obj *
83
- rb_grn_object_finalizer (grn_ctx *context, int n_args, grn_obj **grn_objects,
84
- grn_user_data *user_data)
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 NULL;
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 && rb_grn_object->have_finalizer) {
166
- grn_user_data *user_data;
167
-
168
- user_data = grn_obj_user_data(context, grn_object);
169
- debug("type: %x; need_close: %d; user_data: %p; ptr: %p\n",
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 (user_data && user_data->ptr) {
175
- rb_grn_object_finalizer(context, 1, &grn_object, user_data);
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 0x%x\n",
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
- rb_grn_object_deconstruct(SELF(self), &object, &context,
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
- rb_grn_object_deconstruct(SELF(self), &object, &context,
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
- self, &context, GRN_CURSOR_RK);
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())
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
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-2010 Kouhei Sutou <kou@clear-code.com>
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), NULL);
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
- return rb_grn_record_new(self, id, values);
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>",
@@ -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) ((RbGrnVariableSizeColumn *)DATA_PTR(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
  }
@@ -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 5
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|
@@ -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
  #
@@ -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
@@ -19,7 +19,7 @@ module RroongaBuild
19
19
  module RequiredGroongaVersion
20
20
  MAJOR = 1
21
21
  MINOR = 2
22
- MICRO = 2
22
+ MICRO = 5
23
23
  VERSION = [MAJOR, MINOR, MICRO]
24
24
  end
25
25
 
@@ -22,6 +22,10 @@ class AccessorTest < Test::Unit::TestCase
22
22
  @id = @posts.column("_id")
23
23
  end
24
24
 
25
+ def teardown
26
+ @id = nil
27
+ end
28
+
25
29
  def test_name
26
30
  assert_nil(@id.name)
27
31
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2010 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
@@ -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
@@ -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
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
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
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
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
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
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 test_select_sub_expression
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 test_select_query
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 test_select_query_with_parser
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 test_select_query_with_default_column
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 test_select_expression
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 test_select_query_with_block
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 test_select_query_with_block_match
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 test_select_without_block
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 test_select_query_japanese
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 test_select_but_query
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 test_select_query_with_three_terms
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 test_select_query_with_brackets
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 test_select_equal_reference_column_by_key
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 test_select_not_equal_reference_column_by_key
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 test_select_equal_reference_column_by_nonexistent_key
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 test_select_query_key
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
@@ -23,12 +23,12 @@ class TypeTest < Test::Unit::TestCase
23
23
  assert_equal("user_id", type.name)
24
24
  end
25
25
 
26
- def test_new_with_hyphen_name
26
+ def test_new_with_space_name
27
27
  exception = assert_raise(Groonga::InvalidArgument) do
28
- Groonga::Type.new("user-id", :type => :integer)
28
+ Groonga::Type.new("user id", :type => :integer)
29
29
  end
30
30
  message =
31
- "name can't start with '_' and 0-9, and contains only 0-9, A-Z, a-z, or _"
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: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 5
10
- version: 1.2.5
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-05 00:00:00 Z
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