rroonga 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/doc/text/news.textile +22 -1
- data/ext/groonga/rb-grn-array.c +1 -1
- data/ext/groonga/rb-grn-logger.c +41 -89
- data/ext/groonga/rb-grn-object.c +1 -1
- data/ext/groonga/rb-grn-plugin.c +1 -1
- data/ext/groonga/rb-grn-query-logger.c +75 -2
- data/ext/groonga/rb-grn-table.c +658 -511
- data/ext/groonga/rb-grn-utils.c +113 -22
- data/ext/groonga/rb-grn.h +7 -1
- data/lib/groonga.rb +18 -18
- data/lib/groonga/context.rb +11 -3
- data/lib/groonga/logger.rb +26 -0
- data/lib/groonga/record.rb +25 -2
- data/rroonga-build.rb +1 -1
- data/rroonga.gemspec +1 -1
- data/test/test-column.rb +103 -1
- data/test/test-logger.rb +9 -8
- metadata +4 -4
data/ext/groonga/rb-grn-utils.c
CHANGED
@@ -100,7 +100,7 @@ rb_grn_scan_options (VALUE options, ...)
|
|
100
100
|
VALUE *value;
|
101
101
|
va_list args;
|
102
102
|
|
103
|
-
options =
|
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
|
-
|
590
|
-
|
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
|
-
|
593
|
-
|
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
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
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
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
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
|
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
|
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] ||
|
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
|
38
|
-
require
|
39
|
-
require
|
40
|
-
require
|
41
|
-
require
|
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
|
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
|
94
|
-
require
|
95
|
-
require
|
96
|
-
require
|
97
|
-
require
|
98
|
-
require
|
99
|
-
require
|
100
|
-
require
|
101
|
-
require
|
102
|
-
require
|
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"
|
data/lib/groonga/context.rb
CHANGED
@@ -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
|
-
#
|
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 [
|
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.
|
data/lib/groonga/logger.rb
CHANGED
@@ -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}")
|
data/lib/groonga/record.rb
CHANGED
@@ -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
|
-
#
|
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
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-
|
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
|