rroonga 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -100,7 +100,7 @@ rb_grn_scan_options (VALUE options, ...)
100
100
  VALUE *value;
101
101
  va_list args;
102
102
 
103
- options = rb_check_convert_type(options, T_HASH, "Hash", "to_hash");
103
+ options = rb_grn_check_convert_to_hash(options);
104
104
  if (NIL_P(options)) {
105
105
  if (NIL_P(original_options)) {
106
106
  options = rb_hash_new();
@@ -153,6 +153,44 @@ rb_grn_equal_option (VALUE option, const char *key)
153
153
  return GRN_FALSE;
154
154
  }
155
155
 
156
+ grn_bool
157
+ rb_grn_equal_string (const char *string1, const char *string2)
158
+ {
159
+ if (string1 == string2) {
160
+ return GRN_TRUE;
161
+ }
162
+
163
+ if (!string1 || !string2) {
164
+ return GRN_FALSE;
165
+ }
166
+
167
+ return strcmp(string1, string2) == 0;
168
+ }
169
+
170
+ VALUE
171
+ rb_grn_convert_to_array (VALUE object)
172
+ {
173
+ return rb_convert_type(object, RUBY_T_ARRAY, "Array", "to_ary");
174
+ }
175
+
176
+ VALUE
177
+ rb_grn_check_convert_to_string (VALUE object)
178
+ {
179
+ return rb_check_string_type(object);
180
+ }
181
+
182
+ VALUE
183
+ rb_grn_check_convert_to_array (VALUE object)
184
+ {
185
+ return rb_check_array_type(object);
186
+ }
187
+
188
+ VALUE
189
+ rb_grn_check_convert_to_hash (VALUE object)
190
+ {
191
+ return rb_check_convert_type(object, RUBY_T_HASH, "Hash", "to_hash");
192
+ }
193
+
156
194
  static VALUE
157
195
  rb_grn_bulk_to_ruby_object_by_range_id (grn_ctx *context, grn_obj *bulk,
158
196
  grn_id range_id,
@@ -586,34 +624,87 @@ rb_grn_vector_to_ruby_object (grn_ctx *context, grn_obj *vector)
586
624
  return array;
587
625
  }
588
626
 
589
- grn_obj *
590
- rb_grn_vector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *vector)
627
+ static void
628
+ rb_grn_add_vector_element (VALUE rb_element, grn_ctx *context, grn_obj *vector,
629
+ grn_obj *value_buffer)
591
630
  {
592
- VALUE *values;
593
- grn_obj value;
631
+ unsigned int weight = 0;
632
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_element, rb_cHash))) {
633
+ VALUE rb_value;
634
+ VALUE rb_weight;
635
+ ID id_value;
636
+ ID id_weight;
637
+ CONST_ID(id_value, "value");
638
+ CONST_ID(id_weight, "weight");
639
+ rb_value = rb_hash_aref(rb_element, ID2SYM(id_value));
640
+ rb_weight = rb_hash_aref(rb_element, ID2SYM(id_weight));
641
+ RVAL2GRNOBJ(rb_value, context, &value_buffer);
642
+ if (!NIL_P(rb_weight)) {
643
+ weight = NUM2UINT(rb_weight);
644
+ }
645
+ } else {
646
+ RVAL2GRNOBJ(rb_element, context, &value_buffer);
647
+ }
648
+ grn_vector_add_element(context, vector,
649
+ GRN_BULK_HEAD(value_buffer),
650
+ GRN_BULK_VSIZE(value_buffer),
651
+ weight,
652
+ value_buffer->header.domain);
653
+ }
654
+
655
+ typedef struct {
656
+ VALUE array;
657
+ grn_ctx *context;
658
+ grn_obj *vector;
659
+ grn_obj value_buffer;
660
+ } VectorFromRubyData;
661
+
662
+ static VALUE
663
+ rb_grn_vector_from_ruby_object_body (VALUE user_data)
664
+ {
665
+ VectorFromRubyData *data = (VectorFromRubyData *)user_data;
666
+ VALUE *rb_values;
667
+ grn_ctx *context;
668
+ grn_obj *vector;
669
+ grn_obj *value_buffer;
594
670
  int i, n;
595
671
 
596
- if (vector)
597
- GRN_OBJ_INIT(vector, GRN_VECTOR, 0, GRN_ID_NIL);
598
- else
599
- vector = grn_obj_open(context, GRN_VECTOR, 0, 0);
672
+ n = RARRAY_LEN(data->array);
673
+ rb_values = RARRAY_PTR(data->array);
674
+ context = data->context;
675
+ vector = data->vector;
676
+ value_buffer = &(data->value_buffer);
677
+ for (i = 0; i < n; i++) {
678
+ rb_grn_add_vector_element(rb_values[i], context, vector, value_buffer);
679
+ }
680
+
681
+ return Qnil;
682
+ }
683
+
684
+ static VALUE
685
+ rb_grn_vector_from_ruby_object_ensure (VALUE user_data)
686
+ {
687
+ VectorFromRubyData *data = (VectorFromRubyData *)user_data;
688
+
689
+ GRN_OBJ_FIN(data->context, &(data->value_buffer));
690
+
691
+ return Qnil;
692
+ }
693
+
694
+ grn_obj *
695
+ rb_grn_vector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *vector)
696
+ {
697
+ VectorFromRubyData data;
600
698
 
601
699
  if (NIL_P(object))
602
700
  return vector;
603
701
 
604
- GRN_VOID_INIT(&value);
605
- n = RARRAY_LEN(object);
606
- values = RARRAY_PTR(object);
607
- for (i = 0; i < n; i++) {
608
- grn_obj *_value = &value;
609
- RVAL2GRNOBJ(values[i], context, &_value);
610
- grn_vector_add_element(context, vector,
611
- GRN_BULK_HEAD(&value),
612
- GRN_BULK_VSIZE(&value),
613
- 0,
614
- value.header.domain);
615
- }
616
- GRN_OBJ_FIN(context, &value);
702
+ data.array = rb_grn_convert_to_array(object);
703
+ data.context = context;
704
+ data.vector = vector;
705
+ GRN_VOID_INIT(&(data.value_buffer));
706
+ rb_ensure(rb_grn_vector_from_ruby_object_body, (VALUE)(&data),
707
+ rb_grn_vector_from_ruby_object_ensure, (VALUE)(&data));
617
708
 
618
709
  return vector;
619
710
  }
data/ext/groonga/rb-grn.h CHANGED
@@ -76,7 +76,7 @@ RB_GRN_BEGIN_DECLS
76
76
 
77
77
  #define RB_GRN_MAJOR_VERSION 3
78
78
  #define RB_GRN_MINOR_VERSION 0
79
- #define RB_GRN_MICRO_VERSION 0
79
+ #define RB_GRN_MICRO_VERSION 1
80
80
 
81
81
  #define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
82
82
 
@@ -319,6 +319,12 @@ void rb_grn_scan_options (VALUE options, ...)
319
319
  RB_GRN_GNUC_NULL_TERMINATED;
320
320
  grn_bool rb_grn_equal_option (VALUE option,
321
321
  const char *key);
322
+ grn_bool rb_grn_equal_string (const char *string1,
323
+ const char *string2);
324
+ VALUE rb_grn_convert_to_array (VALUE object);
325
+ VALUE rb_grn_check_convert_to_string (VALUE object);
326
+ VALUE rb_grn_check_convert_to_array (VALUE object);
327
+ VALUE rb_grn_check_convert_to_hash (VALUE object);
322
328
 
323
329
  VALUE rb_grn_object_alloc (VALUE klass);
324
330
  void rb_grn_object_bind (VALUE self,
data/lib/groonga.rb CHANGED
@@ -15,14 +15,14 @@
15
15
  # License along with this library; if not, write to the Free Software
16
16
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
 
18
- require 'pathname'
18
+ require "pathname"
19
19
 
20
20
  base_dir = Pathname.new(__FILE__).dirname.dirname.expand_path
21
21
  local_groonga_dir = base_dir + "vendor" + "local"
22
22
  local_groonga_bin_dir = local_groonga_dir + "bin"
23
23
  if local_groonga_bin_dir.exist?
24
24
  prepend_path = Proc.new do |environment_name, separator|
25
- paths = (ENV[environment_name] || '').split(/#{separator}/)
25
+ paths = (ENV[environment_name] || "").split(/#{separator}/)
26
26
  dir = local_groonga_bin_dir.to_s
27
27
  dir = dir.gsub(/\//, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
28
28
  unless paths.include?(dir)
@@ -34,16 +34,16 @@ if local_groonga_bin_dir.exist?
34
34
  prepend_path.call("PATH", File::PATH_SEPARATOR)
35
35
  end
36
36
 
37
- require 'groonga/geo-point'
38
- require 'groonga/view-record'
39
- require 'groonga/record'
40
- require 'groonga/expression-builder'
41
- require 'groonga/posting'
37
+ require "groonga/geo-point"
38
+ require "groonga/view-record"
39
+ require "groonga/record"
40
+ require "groonga/expression-builder"
41
+ require "groonga/posting"
42
42
  begin
43
43
  major, minor, _ = RUBY_VERSION.split(/\./)
44
44
  require "#{major}.#{minor}/groonga.so"
45
45
  rescue LoadError
46
- require 'groonga.so'
46
+ require "groonga.so"
47
47
  end
48
48
 
49
49
  ##
@@ -90,13 +90,13 @@ module Groonga
90
90
  end
91
91
  end
92
92
 
93
- require 'groonga/context'
94
- require 'groonga/database'
95
- require 'groonga/patricia-trie'
96
- require 'groonga/index-column'
97
- require 'groonga/dumper'
98
- require 'groonga/schema'
99
- require 'groonga/pagination'
100
- require 'groonga/grntest-log'
101
- require 'groonga/logger'
102
- require 'groonga/query-logger'
93
+ require "groonga/context"
94
+ require "groonga/database"
95
+ require "groonga/patricia-trie"
96
+ require "groonga/index-column"
97
+ require "groonga/dumper"
98
+ require "groonga/schema"
99
+ require "groonga/pagination"
100
+ require "groonga/grntest-log"
101
+ require "groonga/logger"
102
+ require "groonga/query-logger"
@@ -137,11 +137,16 @@ module Groonga
137
137
 
138
138
  # Restore commands dumped by "grndump" command.
139
139
  #
140
- # @example Restore dumped commands.
140
+ # @example Restore dumped commands as a String object.
141
141
  # dumped_commands = File.read("dump.grn")
142
142
  # context.restore(dumped_commands)
143
143
  #
144
- # If block is given, response is yielded.
144
+ # @example Restore dumped commands from a File object.
145
+ # File.open("dump.grn") do |file|
146
+ # context.restore(file)
147
+ # end
148
+ #
149
+ # If block is given, a response is yielded.
145
150
  #
146
151
  # @example Restore dumped commands and reports result.
147
152
  # dumped_commands = File.read("dump.grn")
@@ -149,7 +154,10 @@ module Groonga
149
154
  # puts("#{command} -> #{response}")
150
155
  # end
151
156
  #
152
- # @param [String] dumped_commands commands dumped by grndump.
157
+ # @param [#each_line] dumped_commands commands dumped by grndump.
158
+ # It can be a String object or any objects like an IO object such
159
+ # as a File object. It should have #each_line that iterates a
160
+ # line.
153
161
  # @yield [command, response]
154
162
  # Yields a sent command and its response if block is given.
155
163
  # @yieldparam command [String] A sent command.
@@ -42,6 +42,32 @@ module Groonga
42
42
  end
43
43
  end
44
44
 
45
+ class << self
46
+ # @deprecated since 3.0.1. Use {Groonga::Logger.path}
47
+ # instead.
48
+ def log_path
49
+ path
50
+ end
51
+
52
+ # @deprecated since 3.0.1. Use {Groonga::Logger.path=}
53
+ # instead.
54
+ def log_path=(path)
55
+ self.path = path
56
+ end
57
+
58
+ # @deprecated since 3.0.1. Use {Groonga::QueryLogger.path}
59
+ # instead.
60
+ def query_log_path
61
+ QueryLogger.path
62
+ end
63
+
64
+ # @deprecated since 3.0.1. Use {Groonga::QueryLogger.path=}
65
+ # instead.
66
+ def query_log_path=(path)
67
+ QueryLogger.path = path
68
+ end
69
+ end
70
+
45
71
  def log(level, timestamp, title, message, location)
46
72
  guard do
47
73
  puts("#{timestamp}|#{mark(level)}|#{title} #{message} #{location}")
@@ -32,6 +32,9 @@ module Groonga
32
32
  # ...,
33
33
  # ]
34
34
  # </pre>
35
+ #
36
+ # Each value is set by {#[]=}. See {#[]=} how to set weight for a
37
+ # value.
35
38
  def initialize(table, id, values=nil)
36
39
  @table = table
37
40
  @id = id
@@ -67,8 +70,28 @@ module Groonga
67
70
  @table.column_value(@id, column_name, :id => true)
68
71
  end
69
72
 
70
- # このレコードの _column_name_ で指定されたカラムの値を設定す
71
- # る。
73
+ # Sets column value of the record.
74
+ #
75
+ # @overload []=(column_name, value)
76
+ # @param column_name [String] The column name.
77
+ # @param value [Object] The column value. Weight of the value is 0.
78
+ #
79
+ # @example Set a new value
80
+ # user["age"] = 29
81
+ #
82
+ # @overload []=(column_name, value_with_weight)
83
+ # @param column_name [String] The column name.
84
+ # @param value_with_weight [::Hash] The column value with weight.
85
+ # @option value_with_weight [Object] :value (nil) The column value.
86
+ # @option value_with_weight [Integer or nil] :weight (nil)
87
+ # The weight for the value. You need to use vector column and
88
+ # weight supported index column for weight. See
89
+ # {Groonga;:Table#set_column_value} for details.
90
+ #
91
+ # @example Set a new value with weight "2"
92
+ # user["tags"] = [{:value => "groonga", :weight => 2}]
93
+ #
94
+ # @see Groonga::Table#set_column_value
72
95
  def []=(column_name, value)
73
96
  @table.set_column_value(@id, column_name, value, :id => true)
74
97
  end
data/rroonga-build.rb CHANGED
@@ -19,7 +19,7 @@ module RroongaBuild
19
19
  module RequiredGroongaVersion
20
20
  MAJOR = 3
21
21
  MINOR = 0
22
- MICRO = 2
22
+ MICRO = 3
23
23
  VERSION = [MAJOR, MINOR, MICRO]
24
24
  end
25
25
 
data/rroonga.gemspec CHANGED
@@ -88,7 +88,7 @@ Gem::Specification.new do |s|
88
88
  s.add_development_dependency("rake-compiler")
89
89
  s.add_development_dependency("bundler")
90
90
  s.add_development_dependency("yard")
91
- s.add_development_dependency("packnga")
91
+ s.add_development_dependency("packnga", [">= 0.9.7"])
92
92
  s.add_development_dependency("RedCloth")
93
93
  end
94
94
 
data/test/test-column.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2009-2013 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
@@ -347,4 +347,106 @@ class ColumnTest < Test::Unit::TestCase
347
347
  @posts.add("Hello!", :body => "World")
348
348
  @posts.add("My Hobby", :body => "Drive and Eat")
349
349
  end
350
+
351
+ class WeightTest < self
352
+ def setup
353
+ super
354
+ setup_schema
355
+ end
356
+
357
+ def setup_schema
358
+ Groonga::Schema.define do |schema|
359
+ schema.create_table("Shops", :type => :hash) do |table|
360
+ table.short_text("tags", :type => :vector)
361
+ end
362
+
363
+ schema.create_table("Tags",
364
+ :type => :patricia_trie) do |table|
365
+ table.index("Shops.tags", :with_weight => true)
366
+ end
367
+ end
368
+
369
+ @shops = Groonga["Shops"]
370
+ end
371
+
372
+ def test_vector
373
+ @shops.add("Soul Food India",
374
+ :tags => [
375
+ {:value => "curry", :weight => 10},
376
+ {:value => "hot", :weight => 3},
377
+ ])
378
+ assert_equal([["Soul Food India", 11]],
379
+ select_by_tag("curry"))
380
+ end
381
+
382
+ def test_offline_index
383
+ @shops.add("Soul Food India",
384
+ :tags => [
385
+ {:value => "curry", :weight => 10},
386
+ {:value => "hot", :weight => 3},
387
+ ])
388
+ Groonga::Schema.remove_column("Tags", "Shops_tags")
389
+ Groonga::Schema.change_table("Tags") do |table|
390
+ table.index("Shops.tags", :with_weight => true)
391
+ end
392
+
393
+ assert_equal([["Soul Food India", 11]],
394
+ select_by_tag("curry"))
395
+ end
396
+
397
+ private
398
+ def select_by_tag(tag)
399
+ matched_records = @shops.select do |record|
400
+ record.tags =~ tag
401
+ end
402
+ matched_records.collect do |record|
403
+ [record._key, record.score]
404
+ end
405
+ end
406
+
407
+ class UpdateTest < self
408
+ def test_new_value
409
+ record = @shops.add("Soul Food India",
410
+ :tags => [
411
+ {:value => "curry", :weight => 10},
412
+ {:value => "hot", :weight => 3},
413
+ ])
414
+ new_value = "india"
415
+ new_value_weight = 100
416
+ record.tags = [
417
+ {:value => new_value, :weight => new_value_weight},
418
+ ]
419
+ assert_equal([["Soul Food India", new_value_weight + 1]],
420
+ select_by_tag(new_value))
421
+ end
422
+
423
+ def test_old_value
424
+ old_value = "curry"
425
+ record = @shops.add("Soul Food India",
426
+ :tags => [
427
+ {:value => old_value, :weight => 10},
428
+ {:value => "hot", :weight => 3},
429
+ ])
430
+ record.tags = [
431
+ {:value => "india", :weight => 100},
432
+ ]
433
+ assert_equal([], select_by_tag(old_value))
434
+ end
435
+
436
+ def test_replaced_value
437
+ replaced_value = "hot"
438
+ record = @shops.add("Soul Food India",
439
+ :tags => [
440
+ {:value => "curry", :weight => 10},
441
+ {:value => replaced_value, :weight => 3},
442
+ ])
443
+ replaced_value_weight = 100
444
+ record.tags = [
445
+ {:value => replaced_value, :weight => replaced_value_weight},
446
+ ]
447
+ assert_equal([["Soul Food India", replaced_value_weight + 1]],
448
+ select_by_tag(replaced_value))
449
+ end
450
+ end
451
+ end
350
452
  end