rroonga 2.0.6 → 2.0.7
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/Rakefile +4 -0
- data/ext/groonga/rb-grn-index-column.c +9 -3
- data/ext/groonga/rb-grn-index-cursor.c +45 -15
- data/ext/groonga/rb-grn-object.c +20 -6
- data/ext/groonga/rb-grn-patricia-trie.c +2 -2
- data/ext/groonga/rb-grn-posting.c +6 -1
- data/ext/groonga/rb-grn-type.c +104 -1
- data/ext/groonga/rb-grn.h +9 -4
- data/lib/groonga.rb +1 -1
- data/lib/groonga/posting.rb +29 -1
- data/test/test-index-cursor.rb +30 -4
- data/test/test-schema.rb +1 -1
- data/test/test-type.rb +58 -1
- data/test/test-variable-size-column.rb +1 -1
- metadata +4 -7
- data/lib/groonga/query-log.rb +0 -348
- data/test/test-query-log.rb +0 -258
data/Rakefile
CHANGED
@@ -64,7 +64,7 @@ rb_grn_index_column_bind (RbGrnIndexColumn *rb_grn_index_column,
|
|
64
64
|
rb_grn_object->domain_id);
|
65
65
|
rb_grn_index_column->string_query = grn_obj_open(context, GRN_BULK,
|
66
66
|
GRN_OBJ_DO_SHALLOW_COPY,
|
67
|
-
|
67
|
+
GRN_DB_SHORT_TEXT);
|
68
68
|
}
|
69
69
|
|
70
70
|
void
|
@@ -540,23 +540,29 @@ rb_grn_index_column_open_cursor (VALUE self, VALUE rb_table_cursor)
|
|
540
540
|
{
|
541
541
|
grn_ctx *context;
|
542
542
|
grn_obj *column;
|
543
|
+
grn_obj *range_object;
|
543
544
|
grn_table_cursor *table_cursor;
|
544
545
|
grn_id rid_min = GRN_ID_NIL;
|
545
546
|
grn_id rid_max = GRN_ID_MAX;
|
546
547
|
int flags = 0;
|
547
548
|
grn_obj *index_cursor;
|
549
|
+
VALUE rb_table;
|
550
|
+
VALUE rb_lexicon;
|
548
551
|
VALUE rb_cursor;
|
549
552
|
|
550
553
|
rb_grn_index_column_deconstruct(SELF(self), &column, &context,
|
551
554
|
NULL, NULL,
|
552
|
-
NULL, NULL,
|
555
|
+
NULL, NULL,
|
556
|
+
NULL, &range_object,
|
553
557
|
NULL, NULL);
|
554
558
|
table_cursor = RVAL2GRNTABLECURSOR(rb_table_cursor, NULL);
|
559
|
+
rb_table = GRNOBJECT2RVAL(Qnil, context, range_object, GRN_FALSE);
|
560
|
+
rb_lexicon = rb_iv_get(rb_table_cursor, "@table");
|
555
561
|
|
556
562
|
index_cursor = grn_index_cursor_open(context, table_cursor,
|
557
563
|
column, rid_min, rid_max, flags);
|
558
564
|
|
559
|
-
rb_cursor = GRNINDEXCURSOR2RVAL(context, index_cursor);
|
565
|
+
rb_cursor = GRNINDEXCURSOR2RVAL(context, index_cursor, rb_table, rb_lexicon);
|
560
566
|
|
561
567
|
if (rb_block_given_p())
|
562
568
|
return rb_ensure(rb_yield, rb_cursor, rb_grn_object_close, rb_cursor);
|
@@ -26,9 +26,17 @@ VALUE rb_cGrnIndexCursor;
|
|
26
26
|
VALUE
|
27
27
|
rb_grn_index_cursor_to_ruby_object (grn_ctx *context,
|
28
28
|
grn_obj *cursor,
|
29
|
+
VALUE rb_table,
|
30
|
+
VALUE rb_lexicon,
|
29
31
|
grn_bool owner)
|
30
32
|
{
|
31
|
-
|
33
|
+
VALUE rb_cursor;
|
34
|
+
|
35
|
+
rb_cursor = GRNOBJECT2RVAL(rb_cGrnIndexCursor, context, cursor, owner);
|
36
|
+
rb_iv_set(rb_cursor, "@table", rb_table);
|
37
|
+
rb_iv_set(rb_cursor, "@lexicon", rb_lexicon);
|
38
|
+
|
39
|
+
return rb_cursor;
|
32
40
|
}
|
33
41
|
|
34
42
|
void
|
@@ -48,6 +56,20 @@ rb_grn_index_cursor_deconstruct (RbGrnIndexCursor *rb_grn_index_cursor,
|
|
48
56
|
range_id, range);
|
49
57
|
}
|
50
58
|
|
59
|
+
static VALUE
|
60
|
+
next_value (grn_ctx *context, grn_obj *cursor, VALUE rb_table, VALUE rb_lexicon)
|
61
|
+
{
|
62
|
+
grn_posting *posting;
|
63
|
+
grn_id term_id;
|
64
|
+
|
65
|
+
posting = grn_index_cursor_next(context, cursor, &term_id);
|
66
|
+
if (!posting) {
|
67
|
+
return Qnil;
|
68
|
+
}
|
69
|
+
|
70
|
+
return rb_grn_posting_new(posting, term_id, rb_table, rb_lexicon);
|
71
|
+
}
|
72
|
+
|
51
73
|
static VALUE
|
52
74
|
rb_grn_index_cursor_next (VALUE self)
|
53
75
|
{
|
@@ -57,16 +79,12 @@ rb_grn_index_cursor_next (VALUE self)
|
|
57
79
|
|
58
80
|
rb_grn_index_cursor_deconstruct(SELF(self), &cursor, &context,
|
59
81
|
NULL, NULL, NULL, NULL);
|
60
|
-
|
61
82
|
if (context && cursor) {
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
if (posting) {
|
68
|
-
rb_posting = rb_grn_posting_new(posting, tid);
|
69
|
-
}
|
83
|
+
VALUE rb_table;
|
84
|
+
VALUE rb_lexicon;
|
85
|
+
rb_table = rb_iv_get(self, "@table");
|
86
|
+
rb_lexicon = rb_iv_get(self, "@lexicon");
|
87
|
+
rb_posting = next_value(context, cursor, rb_table, rb_lexicon);
|
70
88
|
}
|
71
89
|
|
72
90
|
return rb_posting;
|
@@ -78,19 +96,31 @@ rb_grn_index_cursor_each (VALUE self)
|
|
78
96
|
{
|
79
97
|
grn_obj *cursor;
|
80
98
|
grn_ctx *context;
|
99
|
+
VALUE rb_table;
|
100
|
+
VALUE rb_lexicon;
|
81
101
|
|
82
102
|
RETURN_ENUMERATOR(self, 0, NULL);
|
83
103
|
|
84
104
|
rb_grn_index_cursor_deconstruct(SELF(self), &cursor, &context,
|
85
105
|
NULL, NULL, NULL, NULL);
|
86
106
|
|
87
|
-
if (context
|
88
|
-
|
89
|
-
|
107
|
+
if (!context) {
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
if (!cursor) {
|
112
|
+
return Qnil;
|
113
|
+
}
|
90
114
|
|
91
|
-
|
92
|
-
|
115
|
+
rb_table = rb_iv_get(self, "@table");
|
116
|
+
rb_lexicon = rb_iv_get(self, "@lexicon");
|
117
|
+
while (GRN_TRUE) {
|
118
|
+
VALUE rb_posting;
|
119
|
+
rb_posting = next_value(context, cursor, rb_table, rb_lexicon);
|
120
|
+
if (NIL_P(rb_posting)) {
|
121
|
+
break;
|
93
122
|
}
|
123
|
+
rb_yield(rb_posting);
|
94
124
|
}
|
95
125
|
|
96
126
|
return Qnil;
|
data/ext/groonga/rb-grn-object.c
CHANGED
@@ -821,12 +821,26 @@ rb_grn_object_inspect_content_flags_with_label (VALUE inspected,
|
|
821
821
|
case GRN_COLUMN_FIX_SIZE:
|
822
822
|
case GRN_COLUMN_VAR_SIZE:
|
823
823
|
case GRN_TYPE:
|
824
|
-
if (flags &
|
825
|
-
rb_ary_push(inspected_flags, rb_str_new2("
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
824
|
+
if (flags & GRN_OBJ_KEY_VAR_SIZE) {
|
825
|
+
rb_ary_push(inspected_flags, rb_str_new2("KEY_VAR_SIZE"));
|
826
|
+
} else {
|
827
|
+
switch (flags & GRN_OBJ_KEY_MASK) {
|
828
|
+
case GRN_OBJ_KEY_UINT:
|
829
|
+
rb_ary_push(inspected_flags, rb_str_new2("KEY_UINT"));
|
830
|
+
break;
|
831
|
+
case GRN_OBJ_KEY_INT:
|
832
|
+
rb_ary_push(inspected_flags, rb_str_new2("KEY_INT"));
|
833
|
+
break;
|
834
|
+
case GRN_OBJ_KEY_FLOAT:
|
835
|
+
rb_ary_push(inspected_flags, rb_str_new2("KEY_FLOAT"));
|
836
|
+
break;
|
837
|
+
case GRN_OBJ_KEY_GEO_POINT:
|
838
|
+
rb_ary_push(inspected_flags, rb_str_new2("KEY_GEO_POINT"));
|
839
|
+
break;
|
840
|
+
default:
|
841
|
+
break;
|
842
|
+
}
|
843
|
+
}
|
830
844
|
break;
|
831
845
|
default:
|
832
846
|
break;
|
@@ -19,7 +19,7 @@
|
|
19
19
|
|
20
20
|
#include "rb-grn.h"
|
21
21
|
|
22
|
-
grn_rc grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest,
|
22
|
+
grn_rc grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp);
|
23
23
|
|
24
24
|
#define SELF(object) ((RbGrnTableKeySupport *)DATA_PTR(object))
|
25
25
|
|
@@ -770,7 +770,7 @@ rb_grn_patricia_trie_open_grn_near_cursor (int argc, VALUE *argv, VALUE self,
|
|
770
770
|
grn_ctx_at(*context, table->header.domain));
|
771
771
|
GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain);
|
772
772
|
if (key_p->header.domain != table->header.domain) {
|
773
|
-
grn_obj_cast(*context, key_p, &casted_key,
|
773
|
+
grn_obj_cast(*context, key_p, &casted_key, GRN_FALSE);
|
774
774
|
grn_obj_unlink(*context, key_p);
|
775
775
|
key_p = &casted_key;
|
776
776
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/* -*- coding: utf-8; c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
3
|
Copyright (C) 2011 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
|
4
5
|
|
5
6
|
This library is free software; you can redistribute it and/or
|
6
7
|
modify it under the terms of the GNU Lesser General Public
|
@@ -21,7 +22,8 @@
|
|
21
22
|
VALUE rb_cGrnPosting;
|
22
23
|
|
23
24
|
VALUE
|
24
|
-
rb_grn_posting_new (grn_posting *posting, grn_id term_id
|
25
|
+
rb_grn_posting_new (grn_posting *posting, grn_id term_id,
|
26
|
+
VALUE rb_table, VALUE rb_lexicon)
|
25
27
|
{
|
26
28
|
VALUE parameters;
|
27
29
|
|
@@ -40,6 +42,9 @@ rb_grn_posting_new (grn_posting *posting, grn_id term_id)
|
|
40
42
|
|
41
43
|
#undef SET_PARAMETER
|
42
44
|
|
45
|
+
rb_hash_aset(parameters, ID2SYM(rb_intern("table")), rb_table);
|
46
|
+
rb_hash_aset(parameters, ID2SYM(rb_intern("lexicon")), rb_lexicon);
|
47
|
+
|
43
48
|
return rb_funcall(rb_cGrnPosting, rb_intern("new"), 1,
|
44
49
|
parameters);
|
45
50
|
}
|
data/ext/groonga/rb-grn-type.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- coding: utf-8; c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
|
-
Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
|
3
|
+
Copyright (C) 2009-2012 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
|
@@ -129,12 +129,115 @@ rb_grn_type_initialize (int argc, VALUE *argv, VALUE self)
|
|
129
129
|
return Qnil;
|
130
130
|
}
|
131
131
|
|
132
|
+
static VALUE
|
133
|
+
rb_grn_type_size (VALUE self)
|
134
|
+
{
|
135
|
+
grn_ctx *context;
|
136
|
+
grn_obj *type;
|
137
|
+
|
138
|
+
type = RVAL2GRNOBJECT(self, &context);
|
139
|
+
|
140
|
+
return UINT2NUM(grn_obj_get_range(context, type));
|
141
|
+
}
|
142
|
+
|
143
|
+
static VALUE
|
144
|
+
rb_grn_type_flags (VALUE self)
|
145
|
+
{
|
146
|
+
grn_ctx *context;
|
147
|
+
grn_obj *type;
|
148
|
+
|
149
|
+
type = RVAL2GRNOBJECT(self, &context);
|
150
|
+
|
151
|
+
return UINT2NUM(type->header.flags);
|
152
|
+
}
|
153
|
+
|
154
|
+
static VALUE
|
155
|
+
rb_grn_type_fixed_size_p (VALUE self)
|
156
|
+
{
|
157
|
+
grn_ctx *context;
|
158
|
+
grn_obj *type;
|
159
|
+
|
160
|
+
type = RVAL2GRNOBJECT(self, &context);
|
161
|
+
|
162
|
+
return CBOOL2RVAL(!(type->header.flags & GRN_OBJ_KEY_VAR_SIZE));
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE
|
166
|
+
rb_grn_type_variable_size_p (VALUE self)
|
167
|
+
{
|
168
|
+
grn_ctx *context;
|
169
|
+
grn_obj *type;
|
170
|
+
|
171
|
+
type = RVAL2GRNOBJECT(self, &context);
|
172
|
+
|
173
|
+
return CBOOL2RVAL(type->header.flags & GRN_OBJ_KEY_VAR_SIZE);
|
174
|
+
}
|
175
|
+
|
176
|
+
static VALUE
|
177
|
+
rb_grn_type_unsigned_integer_p (VALUE self)
|
178
|
+
{
|
179
|
+
grn_obj *type;
|
180
|
+
grn_obj_flags key_type;
|
181
|
+
|
182
|
+
type = RVAL2GRNOBJECT(self, NULL);
|
183
|
+
key_type = type->header.flags & GRN_OBJ_KEY_MASK;
|
184
|
+
return CBOOL2RVAL(key_type == GRN_OBJ_KEY_UINT);
|
185
|
+
}
|
186
|
+
|
187
|
+
static VALUE
|
188
|
+
rb_grn_type_integer_p (VALUE self)
|
189
|
+
{
|
190
|
+
grn_obj *type;
|
191
|
+
grn_obj_flags key_type;
|
192
|
+
|
193
|
+
type = RVAL2GRNOBJECT(self, NULL);
|
194
|
+
key_type = type->header.flags & GRN_OBJ_KEY_MASK;
|
195
|
+
return CBOOL2RVAL(key_type == GRN_OBJ_KEY_INT);
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE
|
199
|
+
rb_grn_type_float_p (VALUE self)
|
200
|
+
{
|
201
|
+
grn_obj *type;
|
202
|
+
grn_obj_flags key_type;
|
203
|
+
|
204
|
+
type = RVAL2GRNOBJECT(self, NULL);
|
205
|
+
key_type = type->header.flags & GRN_OBJ_KEY_MASK;
|
206
|
+
return CBOOL2RVAL(key_type == GRN_OBJ_KEY_FLOAT);
|
207
|
+
}
|
208
|
+
|
209
|
+
static VALUE
|
210
|
+
rb_grn_type_geo_point_p (VALUE self)
|
211
|
+
{
|
212
|
+
grn_obj *type;
|
213
|
+
grn_obj_flags key_type;
|
214
|
+
|
215
|
+
type = RVAL2GRNOBJECT(self, NULL);
|
216
|
+
key_type = type->header.flags & GRN_OBJ_KEY_MASK;
|
217
|
+
return CBOOL2RVAL(key_type == GRN_OBJ_KEY_GEO_POINT);
|
218
|
+
}
|
219
|
+
|
132
220
|
void
|
133
221
|
rb_grn_init_type (VALUE mGrn)
|
134
222
|
{
|
135
223
|
rb_cGrnType = rb_define_class_under(mGrn, "Type", rb_cGrnObject);
|
136
224
|
|
137
225
|
rb_define_method(rb_cGrnType, "initialize", rb_grn_type_initialize, -1);
|
226
|
+
rb_define_method(rb_cGrnType, "size", rb_grn_type_size, 0);
|
227
|
+
rb_define_method(rb_cGrnType, "flags", rb_grn_type_flags, 0);
|
228
|
+
rb_define_method(rb_cGrnType, "fixed_size?", rb_grn_type_fixed_size_p, 0);
|
229
|
+
rb_define_method(rb_cGrnType, "variable_size?",
|
230
|
+
rb_grn_type_variable_size_p, 0);
|
231
|
+
|
232
|
+
rb_define_method(rb_cGrnType, "unsigned_integer?",
|
233
|
+
rb_grn_type_unsigned_integer_p, 0);
|
234
|
+
rb_define_alias(rb_cGrnType, "uint?", "unsigned_integer?");
|
235
|
+
|
236
|
+
rb_define_method(rb_cGrnType, "integer?", rb_grn_type_integer_p, 0);
|
237
|
+
rb_define_alias(rb_cGrnType, "int?", "integer?");
|
238
|
+
|
239
|
+
rb_define_method(rb_cGrnType, "float?", rb_grn_type_float_p, 0);
|
240
|
+
rb_define_method(rb_cGrnType, "geo_point?", rb_grn_type_geo_point_p, 0);
|
138
241
|
|
139
242
|
/* 任意のテーブルに属する全てのレコード(Object型はv1.2で
|
140
243
|
サポートされます)。 */
|
data/ext/groonga/rb-grn.h
CHANGED
@@ -76,7 +76,7 @@ RB_GRN_BEGIN_DECLS
|
|
76
76
|
|
77
77
|
#define RB_GRN_MAJOR_VERSION 2
|
78
78
|
#define RB_GRN_MINOR_VERSION 0
|
79
|
-
#define RB_GRN_MICRO_VERSION
|
79
|
+
#define RB_GRN_MICRO_VERSION 7
|
80
80
|
|
81
81
|
#define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
|
82
82
|
|
@@ -503,7 +503,9 @@ void rb_grn_expression_finalizer (grn_ctx *context,
|
|
503
503
|
RbGrnExpression *rb_grn_expression);
|
504
504
|
|
505
505
|
VALUE rb_grn_posting_new (grn_posting *posting,
|
506
|
-
grn_id term_id
|
506
|
+
grn_id term_id,
|
507
|
+
VALUE rb_table,
|
508
|
+
VALUE rb_lexicon);
|
507
509
|
|
508
510
|
VALUE rb_grn_tokyo_geo_point_new (int latitude,
|
509
511
|
int longitude);
|
@@ -582,8 +584,9 @@ VALUE rb_grn_column_expression_builder_build
|
|
582
584
|
#define GRNCOLUMN2RVAL(klass, context, column, owner) \
|
583
585
|
(rb_grn_column_to_ruby_object(klass, context, column, owner))
|
584
586
|
|
585
|
-
#define GRNINDEXCURSOR2RVAL(context, cursor) \
|
586
|
-
(rb_grn_index_cursor_to_ruby_object(context, cursor,
|
587
|
+
#define GRNINDEXCURSOR2RVAL(context, cursor, rb_table, rb_lexicon) \
|
588
|
+
(rb_grn_index_cursor_to_ruby_object(context, cursor, rb_table, rb_lexicon, \
|
589
|
+
GRN_TRUE))
|
587
590
|
|
588
591
|
#define RVAL2GRNACCESSOR(object) \
|
589
592
|
(rb_grn_accessor_from_ruby_object(object))
|
@@ -695,6 +698,8 @@ VALUE rb_grn_column_to_ruby_object (VALUE klass,
|
|
695
698
|
grn_bool owner);
|
696
699
|
VALUE rb_grn_index_cursor_to_ruby_object (grn_ctx *context,
|
697
700
|
grn_obj *cursor,
|
701
|
+
VALUE rb_table,
|
702
|
+
VALUE rb_lexicon,
|
698
703
|
grn_bool owner);
|
699
704
|
|
700
705
|
grn_operator rb_grn_operator_from_ruby_object (VALUE object);
|
data/lib/groonga.rb
CHANGED
data/lib/groonga/posting.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
|
3
|
+
# Copyright (C) 2011-2012 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
|
@@ -43,6 +43,12 @@ module Groonga
|
|
43
43
|
# The number of rest posting information for the term ID.
|
44
44
|
attr_accessor :n_rest_postings
|
45
45
|
|
46
|
+
# @return [Groonga::Table] The table of the record ID.
|
47
|
+
attr_reader :table
|
48
|
+
|
49
|
+
# @return [Groonga::Table] The table of the term ID.
|
50
|
+
attr_reader :lexicon
|
51
|
+
|
46
52
|
# Creates a new Posting.
|
47
53
|
#
|
48
54
|
# @return The new Posting.
|
@@ -61,6 +67,8 @@ module Groonga
|
|
61
67
|
# @option parameters [Integer] :term_frequency The term_frequency.
|
62
68
|
# @option parameters [Integer] :weight The weight.
|
63
69
|
# @option parameters [Integer] :n_rest_postings The n_rest_postings.
|
70
|
+
# @option parameters [Groonga::Table] :table The table of the record ID.
|
71
|
+
# @option parameters [Groonga::Table] :lexicon The table of the term ID.
|
64
72
|
def update(parameters)
|
65
73
|
@record_id = parameters[:record_id] || nil
|
66
74
|
@section_id = parameters[:section_id] || nil
|
@@ -69,6 +77,8 @@ module Groonga
|
|
69
77
|
@term_frequency = parameters[:term_frequency] || 0
|
70
78
|
@weight = parameters[:weight] || 0
|
71
79
|
@n_rest_postings = parameters[:n_rest_postings] || 0
|
80
|
+
@table = parameters[:table]
|
81
|
+
@lexicon = parameters[:lexicon]
|
72
82
|
end
|
73
83
|
|
74
84
|
# Returns Hash created from attributes.
|
@@ -83,5 +93,23 @@ module Groonga
|
|
83
93
|
:n_rest_postings => @n_rest_postings
|
84
94
|
}
|
85
95
|
end
|
96
|
+
|
97
|
+
# @return [Groonga::Record, nil] The record for the record ID.
|
98
|
+
# If table isn't assosiated, nil is returned.
|
99
|
+
#
|
100
|
+
# @since 2.0.6
|
101
|
+
def record
|
102
|
+
return nil unless @table
|
103
|
+
Record.new(@table, @record_id)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Groonga::Record, nil] The record for the term ID.
|
107
|
+
# If lexicon isn't assosiated, nil is returned.
|
108
|
+
#
|
109
|
+
# @since 2.0.6
|
110
|
+
def term
|
111
|
+
return nil unless @lexicon
|
112
|
+
Record.new(@lexicon, @term_id)
|
113
|
+
end
|
86
114
|
end
|
87
115
|
end
|
data/test/test-index-cursor.rb
CHANGED
@@ -66,6 +66,30 @@ class IndexCursorTest < Test::Unit::TestCase
|
|
66
66
|
assert_true(opened)
|
67
67
|
end
|
68
68
|
|
69
|
+
def test_record
|
70
|
+
record = nil
|
71
|
+
@terms.open_cursor do |table_cursor|
|
72
|
+
@content_index.open_cursor(table_cursor) do |cursor|
|
73
|
+
posting = cursor.next
|
74
|
+
record = posting.record
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal("1", record.key)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_term
|
82
|
+
term = nil
|
83
|
+
@terms.open_cursor do |table_cursor|
|
84
|
+
@content_index.open_cursor(table_cursor) do |cursor|
|
85
|
+
posting = cursor.next
|
86
|
+
term = posting.term
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
assert_equal("l", term.key)
|
91
|
+
end
|
92
|
+
|
69
93
|
private
|
70
94
|
def create_hashes(keys, values)
|
71
95
|
hashes = []
|
@@ -81,7 +105,9 @@ class IndexCursorTest < Test::Unit::TestCase
|
|
81
105
|
|
82
106
|
def setup_schema
|
83
107
|
Groonga::Schema.define do |schema|
|
84
|
-
schema.create_table("Articles"
|
108
|
+
schema.create_table("Articles",
|
109
|
+
:type => :hash,
|
110
|
+
:key_type => :short_text) do |table|
|
85
111
|
table.text("content")
|
86
112
|
end
|
87
113
|
|
@@ -98,9 +124,9 @@ class IndexCursorTest < Test::Unit::TestCase
|
|
98
124
|
end
|
99
125
|
|
100
126
|
def setup_records
|
101
|
-
@articles.add(:content => "l")
|
102
|
-
@articles.add(:content => "ll")
|
103
|
-
@articles.add(:content => "hello")
|
127
|
+
@articles.add("1", :content => "l")
|
128
|
+
@articles.add("2", :content => "ll")
|
129
|
+
@articles.add("3", :content => "hello")
|
104
130
|
end
|
105
131
|
|
106
132
|
def expected_postings
|
data/test/test-schema.rb
CHANGED
data/test/test-type.rb
CHANGED
@@ -33,6 +33,63 @@ class TypeTest < Test::Unit::TestCase
|
|
33
33
|
exception.message)
|
34
34
|
end
|
35
35
|
|
36
|
+
def test_size
|
37
|
+
assert_equal(4, Groonga["Int32"].size)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_flags
|
41
|
+
key_int = 0x01 << 3
|
42
|
+
assert_equal(key_int, Groonga["Int32"].flags)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_fixed_size?
|
46
|
+
assert_true(Groonga["Int32"].fixed_size?)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_not_fixed_size?
|
50
|
+
assert_false(Groonga["ShortText"].fixed_size?)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_variable_size?
|
54
|
+
assert_true(Groonga["ShortText"].variable_size?)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_not_variable_size?
|
58
|
+
assert_false(Groonga["Int32"].variable_size?)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_unsigned_integer?
|
62
|
+
assert_true(Groonga["UInt32"].unsigned_integer?)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_not_unsigned_integer?
|
66
|
+
assert_false(Groonga["Int32"].unsigned_integer?)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_integer?
|
70
|
+
assert_true(Groonga["Int32"].integer?)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_not_integer?
|
74
|
+
assert_false(Groonga["UInt32"].integer?)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_float?
|
78
|
+
assert_true(Groonga["Float"].float?)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_not_float?
|
82
|
+
assert_false(Groonga["UInt32"].float?)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_geo_point?
|
86
|
+
assert_true(Groonga["WGS84GeoPoint"].geo_point?)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_not_geo_point?
|
90
|
+
assert_false(Groonga["UInt32"].geo_point?)
|
91
|
+
end
|
92
|
+
|
36
93
|
def test_builtins
|
37
94
|
assert_equal_type("Object", Groonga::Type::OBJECT) # FIXME!!!
|
38
95
|
assert_equal_type("Bool", Groonga::Type::BOOLEAN)
|
@@ -58,7 +115,7 @@ class TypeTest < Test::Unit::TestCase
|
|
58
115
|
"path: (temporary), " +
|
59
116
|
"domain: (nil), " +
|
60
117
|
"range: <2147483648>, " +
|
61
|
-
"flags:
|
118
|
+
"flags: <KEY_VAR_SIZE>>",
|
62
119
|
context["<longtext>"].inspect)
|
63
120
|
end
|
64
121
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rroonga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pkg-config
|
@@ -224,7 +224,6 @@ files:
|
|
224
224
|
- lib/groonga/context.rb
|
225
225
|
- lib/groonga/grntest-log.rb
|
226
226
|
- lib/groonga/geo-point.rb
|
227
|
-
- lib/groonga/query-log.rb
|
228
227
|
- lib/groonga/pagination.rb
|
229
228
|
- lib/groonga/command.rb
|
230
229
|
- lib/groonga/schema.rb
|
@@ -312,7 +311,6 @@ files:
|
|
312
311
|
- test/groonga-test-utils.rb
|
313
312
|
- test/test-table-dumper.rb
|
314
313
|
- test/test-schema-type.rb
|
315
|
-
- test/test-query-log.rb
|
316
314
|
- test/test-patricia-trie.rb
|
317
315
|
- test/test-version.rb
|
318
316
|
- test/test-table-traverse.rb
|
@@ -349,7 +347,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
349
347
|
version: '0'
|
350
348
|
segments:
|
351
349
|
- 0
|
352
|
-
hash:
|
350
|
+
hash: 3736378040968072494
|
353
351
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
354
352
|
none: false
|
355
353
|
requirements:
|
@@ -358,7 +356,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
358
356
|
version: '0'
|
359
357
|
segments:
|
360
358
|
- 0
|
361
|
-
hash:
|
359
|
+
hash: 3736378040968072494
|
362
360
|
requirements: []
|
363
361
|
rubyforge_project: groonga
|
364
362
|
rubygems_version: 1.8.23
|
@@ -396,7 +394,6 @@ test_files:
|
|
396
394
|
- test/groonga-test-utils.rb
|
397
395
|
- test/test-table-dumper.rb
|
398
396
|
- test/test-schema-type.rb
|
399
|
-
- test/test-query-log.rb
|
400
397
|
- test/test-patricia-trie.rb
|
401
398
|
- test/test-version.rb
|
402
399
|
- test/test-table-traverse.rb
|
data/lib/groonga/query-log.rb
DELETED
@@ -1,348 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
#
|
3
|
-
# Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License version 2.1 as published by the Free Software Foundation.
|
8
|
-
#
|
9
|
-
# This library is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
-
# Lesser General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU Lesser General Public
|
15
|
-
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
-
|
18
|
-
require "English"
|
19
|
-
require "shellwords"
|
20
|
-
require "cgi"
|
21
|
-
|
22
|
-
module Groonga
|
23
|
-
module QueryLog
|
24
|
-
class Command
|
25
|
-
class << self
|
26
|
-
@@registered_commands = {}
|
27
|
-
def register(name, klass)
|
28
|
-
@@registered_commands[name] = klass
|
29
|
-
end
|
30
|
-
|
31
|
-
def parse(input)
|
32
|
-
if input.start_with?("/d/")
|
33
|
-
parse_uri_path(input)
|
34
|
-
else
|
35
|
-
parse_command_line(input)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
def parse_uri_path(path)
|
41
|
-
name, parameters_string = path.split(/\?/, 2)
|
42
|
-
parameters = {}
|
43
|
-
if parameters_string
|
44
|
-
parameters_string.split(/&/).each do |parameter_string|
|
45
|
-
key, value = parameter_string.split(/\=/, 2)
|
46
|
-
parameters[key] = CGI.unescape(value)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
name = name.gsub(/\A\/d\//, '')
|
50
|
-
name, output_type = name.split(/\./, 2)
|
51
|
-
parameters["output_type"] = output_type if output_type
|
52
|
-
command_class = @@registered_commands[name] || self
|
53
|
-
command = command_class.new(name, parameters)
|
54
|
-
command.original_format = :uri
|
55
|
-
command
|
56
|
-
end
|
57
|
-
|
58
|
-
def parse_command_line(command_line)
|
59
|
-
name, *options = Shellwords.shellwords(command_line)
|
60
|
-
parameters = {}
|
61
|
-
options.each_slice(2) do |key, value|
|
62
|
-
parameters[key.gsub(/\A--/, '')] = value
|
63
|
-
end
|
64
|
-
command_class = @@registered_commands[name] || self
|
65
|
-
command = command_class.new(name, parameters)
|
66
|
-
command.original_format = :command
|
67
|
-
command
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
attr_reader :name, :parameters
|
72
|
-
attr_accessor :original_format
|
73
|
-
def initialize(name, parameters)
|
74
|
-
@name = name
|
75
|
-
@parameters = parameters
|
76
|
-
@original_format = nil
|
77
|
-
end
|
78
|
-
|
79
|
-
def ==(other)
|
80
|
-
other.is_a?(self.class) and
|
81
|
-
@name == other.name and
|
82
|
-
@parameters == other.parameters
|
83
|
-
end
|
84
|
-
|
85
|
-
def uri_format?
|
86
|
-
@original_format == :uri
|
87
|
-
end
|
88
|
-
|
89
|
-
def command_format?
|
90
|
-
@original_format == :command
|
91
|
-
end
|
92
|
-
|
93
|
-
def to_uri_format
|
94
|
-
path = "/d/#{@name}"
|
95
|
-
parameters = @parameters.dup
|
96
|
-
output_type = parameters.delete("output_type")
|
97
|
-
path << ".#{output_type}" if output_type
|
98
|
-
unless parameters.empty?
|
99
|
-
sorted_parameters = parameters.sort_by do |name, _|
|
100
|
-
name.to_s
|
101
|
-
end
|
102
|
-
uri_parameters = sorted_parameters.collect do |name, value|
|
103
|
-
"#{CGI.escape(name)}=#{CGI.escape(value)}"
|
104
|
-
end
|
105
|
-
path << "?"
|
106
|
-
path << uri_parameters.join("&")
|
107
|
-
end
|
108
|
-
path
|
109
|
-
end
|
110
|
-
|
111
|
-
def to_command_format
|
112
|
-
command_line = [@name]
|
113
|
-
sorted_parameters = @parameters.sort_by do |name, _|
|
114
|
-
name.to_s
|
115
|
-
end
|
116
|
-
sorted_parameters.each do |name, value|
|
117
|
-
escaped_value = value.gsub(/[\n"\\]/) do
|
118
|
-
special_character = $MATCH
|
119
|
-
case special_character
|
120
|
-
when "\n"
|
121
|
-
"\\n"
|
122
|
-
else
|
123
|
-
"\\#{special_character}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
command_line << "--#{name}"
|
127
|
-
command_line << "\"#{escaped_value}\""
|
128
|
-
end
|
129
|
-
command_line.join(" ")
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
class SelectCommand < Command
|
134
|
-
register("select", self)
|
135
|
-
|
136
|
-
def sortby
|
137
|
-
@parameters["sortby"]
|
138
|
-
end
|
139
|
-
|
140
|
-
def scorer
|
141
|
-
@parameters["scorer"]
|
142
|
-
end
|
143
|
-
|
144
|
-
def query
|
145
|
-
@parameters["query"]
|
146
|
-
end
|
147
|
-
|
148
|
-
def filter
|
149
|
-
@parameters["filter"]
|
150
|
-
end
|
151
|
-
|
152
|
-
def conditions
|
153
|
-
@conditions ||= filter.split(/(?:&&|&!|\|\|)/).collect do |condition|
|
154
|
-
condition = condition.strip
|
155
|
-
condition = condition.gsub(/\A[\s\(]*/, '')
|
156
|
-
condition = condition.gsub(/[\s\)]*\z/, '') unless /\(/ =~ condition
|
157
|
-
condition
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def drilldowns
|
162
|
-
@drilldowns ||= (@parameters["drilldown"] || "").split(/\s*,\s*/)
|
163
|
-
end
|
164
|
-
|
165
|
-
def output_columns
|
166
|
-
@parameters["output_columns"]
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
class Statistic
|
171
|
-
attr_reader :context_id, :start_time, :raw_command
|
172
|
-
attr_reader :elapsed, :return_code
|
173
|
-
attr_accessor :slow_operation_threshold, :slow_response_threshold
|
174
|
-
def initialize(context_id)
|
175
|
-
@context_id = context_id
|
176
|
-
@start_time = nil
|
177
|
-
@command = nil
|
178
|
-
@raw_command = nil
|
179
|
-
@operations = []
|
180
|
-
@elapsed = nil
|
181
|
-
@return_code = 0
|
182
|
-
@slow_operation_threshold = 0.1
|
183
|
-
@slow_response_threshold = 0.2
|
184
|
-
end
|
185
|
-
|
186
|
-
def start(start_time, command)
|
187
|
-
@start_time = start_time
|
188
|
-
@raw_command = command
|
189
|
-
end
|
190
|
-
|
191
|
-
def finish(elapsed, return_code)
|
192
|
-
@elapsed = elapsed
|
193
|
-
@return_code = return_code
|
194
|
-
end
|
195
|
-
|
196
|
-
def command
|
197
|
-
@command ||= Command.parse(@raw_command)
|
198
|
-
end
|
199
|
-
|
200
|
-
def elapsed_in_seconds
|
201
|
-
nano_seconds_to_seconds(@elapsed)
|
202
|
-
end
|
203
|
-
|
204
|
-
def last_time
|
205
|
-
@start_time + elapsed_in_seconds
|
206
|
-
end
|
207
|
-
|
208
|
-
def slow?
|
209
|
-
elapsed_in_seconds >= @slow_response_threshold
|
210
|
-
end
|
211
|
-
|
212
|
-
def each_operation
|
213
|
-
previous_elapsed = 0
|
214
|
-
ensure_parse_command
|
215
|
-
operation_context_context = {
|
216
|
-
:filter_index => 0,
|
217
|
-
:drilldown_index => 0,
|
218
|
-
}
|
219
|
-
@operations.each_with_index do |operation, i|
|
220
|
-
relative_elapsed = operation[:elapsed] - previous_elapsed
|
221
|
-
relative_elapsed_in_seconds = nano_seconds_to_seconds(relative_elapsed)
|
222
|
-
previous_elapsed = operation[:elapsed]
|
223
|
-
parsed_operation = {
|
224
|
-
:i => i,
|
225
|
-
:elapsed => operation[:elapsed],
|
226
|
-
:elapsed_in_seconds => nano_seconds_to_seconds(operation[:elapsed]),
|
227
|
-
:relative_elapsed => relative_elapsed,
|
228
|
-
:relative_elapsed_in_seconds => relative_elapsed_in_seconds,
|
229
|
-
:name => operation[:name],
|
230
|
-
:context => operation_context(operation[:name],
|
231
|
-
operation_context_context),
|
232
|
-
:n_records => operation[:n_records],
|
233
|
-
:slow? => slow_operation?(relative_elapsed_in_seconds),
|
234
|
-
}
|
235
|
-
yield parsed_operation
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
def add_operation(operation)
|
240
|
-
@operations << operation
|
241
|
-
end
|
242
|
-
|
243
|
-
def operations
|
244
|
-
_operations = []
|
245
|
-
each_operation do |operation|
|
246
|
-
_operations << operation
|
247
|
-
end
|
248
|
-
_operations
|
249
|
-
end
|
250
|
-
|
251
|
-
def select_command?
|
252
|
-
command.name == "select"
|
253
|
-
end
|
254
|
-
|
255
|
-
private
|
256
|
-
def nano_seconds_to_seconds(nano_seconds)
|
257
|
-
nano_seconds / 1000.0 / 1000.0 / 1000.0
|
258
|
-
end
|
259
|
-
|
260
|
-
def operation_context(label, context)
|
261
|
-
case label
|
262
|
-
when "filter"
|
263
|
-
if @select_command.query and context[:query_used].nil?
|
264
|
-
context[:query_used] = true
|
265
|
-
"query: #{@select_command.query}"
|
266
|
-
else
|
267
|
-
index = context[:filter_index]
|
268
|
-
context[:filter_index] += 1
|
269
|
-
@select_command.conditions[index]
|
270
|
-
end
|
271
|
-
when "sort"
|
272
|
-
@select_command.sortby
|
273
|
-
when "score"
|
274
|
-
@select_command.scorer
|
275
|
-
when "output"
|
276
|
-
@select_command.output_columns
|
277
|
-
when "drilldown"
|
278
|
-
index = context[:drilldown_index]
|
279
|
-
context[:drilldown_index] += 1
|
280
|
-
@select_command.drilldowns[index]
|
281
|
-
else
|
282
|
-
nil
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def ensure_parse_command
|
287
|
-
return unless select_command?
|
288
|
-
@select_command = SelectCommand.parse(@raw_command)
|
289
|
-
end
|
290
|
-
|
291
|
-
def slow_operation?(elapsed)
|
292
|
-
elapsed >= @slow_operation_threshold
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
class Parser
|
297
|
-
def initialize
|
298
|
-
end
|
299
|
-
|
300
|
-
def parse(input, &block)
|
301
|
-
current_statistics = {}
|
302
|
-
input.each_line do |line|
|
303
|
-
case line
|
304
|
-
when /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\.(\d+)\|(.+?)\|([>:<])/
|
305
|
-
year, month, day, hour, minutes, seconds, micro_seconds =
|
306
|
-
$1, $2, $3, $4, $5, $6, $7
|
307
|
-
context_id = $8
|
308
|
-
type = $9
|
309
|
-
rest = $POSTMATCH.strip
|
310
|
-
time_stamp = Time.local(year, month, day, hour, minutes, seconds,
|
311
|
-
micro_seconds)
|
312
|
-
parse_line(current_statistics,
|
313
|
-
time_stamp, context_id, type, rest, &block)
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
private
|
319
|
-
def parse_line(current_statistics,
|
320
|
-
time_stamp, context_id, type, rest, &block)
|
321
|
-
case type
|
322
|
-
when ">"
|
323
|
-
statistic = Statistic.new(context_id)
|
324
|
-
statistic.start(time_stamp, rest)
|
325
|
-
current_statistics[context_id] = statistic
|
326
|
-
when ":"
|
327
|
-
return unless /\A(\d+) (.+)\((\d+)\)/ =~ rest
|
328
|
-
elapsed = $1
|
329
|
-
name = $2
|
330
|
-
n_records = $3.to_i
|
331
|
-
statistic = current_statistics[context_id]
|
332
|
-
return if statistic.nil?
|
333
|
-
statistic.add_operation(:name => name,
|
334
|
-
:elapsed => elapsed.to_i,
|
335
|
-
:n_records => n_records)
|
336
|
-
when "<"
|
337
|
-
return unless /\A(\d+) rc=(\d+)/ =~ rest
|
338
|
-
elapsed = $1
|
339
|
-
return_code = $2
|
340
|
-
statistic = current_statistics.delete(context_id)
|
341
|
-
return if statistic.nil?
|
342
|
-
statistic.finish(elapsed.to_i, return_code.to_i)
|
343
|
-
block.call(statistic)
|
344
|
-
end
|
345
|
-
end
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
data/test/test-query-log.rb
DELETED
@@ -1,258 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
# Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
|
3
|
-
#
|
4
|
-
# This library is free software; you can redistribute it and/or
|
5
|
-
# modify it under the terms of the GNU Lesser General Public
|
6
|
-
# License version 2.1 as published by the Free Software Foundation.
|
7
|
-
#
|
8
|
-
# This library is distributed in the hope that it will be useful,
|
9
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
-
# Lesser General Public License for more details.
|
12
|
-
#
|
13
|
-
# You should have received a copy of the GNU Lesser General Public
|
14
|
-
# License along with this library; if not, write to the Free Software
|
15
|
-
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
16
|
-
|
17
|
-
require "cgi"
|
18
|
-
|
19
|
-
module QueryLogTest
|
20
|
-
module CommandParseTestUtils
|
21
|
-
private
|
22
|
-
def command(name, parameters)
|
23
|
-
Groonga::QueryLog::Command.new(name, parameters)
|
24
|
-
end
|
25
|
-
|
26
|
-
def parse_http_path(command, parameters)
|
27
|
-
path = "/d/#{command}.json"
|
28
|
-
unless parameters.empty?
|
29
|
-
uri_parameters = parameters.collect do |key, value|
|
30
|
-
[CGI.escape(key.to_s), CGI.escape(value.to_s)].join("=")
|
31
|
-
end
|
32
|
-
path << "?"
|
33
|
-
path << uri_parameters.join("&")
|
34
|
-
end
|
35
|
-
Groonga::QueryLog::Command.parse(path)
|
36
|
-
end
|
37
|
-
|
38
|
-
def parse_command_line(command, parameters)
|
39
|
-
command_line = "#{command} --output_type json"
|
40
|
-
parameters.each do |key, value|
|
41
|
-
if /"| / =~ value
|
42
|
-
escaped_value = '"' + value.gsub(/"/, '\"') + '"'
|
43
|
-
else
|
44
|
-
escaped_value = value
|
45
|
-
end
|
46
|
-
command_line << " --#{key} #{escaped_value}"
|
47
|
-
end
|
48
|
-
Groonga::QueryLog::Command.parse(command_line)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
module HTTPCommandParseTestUtils
|
53
|
-
private
|
54
|
-
def parse(command, parameters={})
|
55
|
-
parse_http_path(command, parameters)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
module CommandLineCommandParseTestUtils
|
60
|
-
private
|
61
|
-
def parse(command, parameters={})
|
62
|
-
parse_command_line(command, parameters)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
module SelectCommandParseTests
|
67
|
-
include CommandParseTestUtils
|
68
|
-
|
69
|
-
def test_parameters
|
70
|
-
select = parse("select",
|
71
|
-
:table => "Users",
|
72
|
-
:filter => "age<=30")
|
73
|
-
assert_equal(command("select",
|
74
|
-
"table" => "Users",
|
75
|
-
"filter" => "age<=30",
|
76
|
-
"output_type" => "json"),
|
77
|
-
select)
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_scorer
|
81
|
-
select = parse("select",
|
82
|
-
:table => "Users",
|
83
|
-
:filter => "age<=30",
|
84
|
-
:scorer => "_score = random()")
|
85
|
-
assert_equal("_score = random()", select.scorer)
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_to_uri_format
|
89
|
-
select = parse("select",
|
90
|
-
:table => "Users",
|
91
|
-
:filter => "age<=30")
|
92
|
-
assert_equal("/d/select.json?filter=age%3C%3D30&table=Users",
|
93
|
-
select.to_uri_format)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_to_command_format
|
97
|
-
select = parse("select",
|
98
|
-
:table => "Users",
|
99
|
-
:filter => "age<=30")
|
100
|
-
assert_equal("select --filter \"age<=30\" " +
|
101
|
-
"--output_type \"json\" --table \"Users\"",
|
102
|
-
select.to_command_format)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
module SelectCommandParseFilterTests
|
107
|
-
include CommandParseTestUtils
|
108
|
-
|
109
|
-
def test_parenthesis
|
110
|
-
filter = 'geo_in_rectangle(location,' +
|
111
|
-
'"35.73360x139.7394","62614x139.7714") && ' +
|
112
|
-
'((type == "たいやき" || type == "和菓子")) && ' +
|
113
|
-
'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
|
114
|
-
select = parse("select",
|
115
|
-
:table => "Users",
|
116
|
-
:filter => filter)
|
117
|
-
assert_equal(['geo_in_rectangle(location,' +
|
118
|
-
'"35.73360x139.7394","62614x139.7714")',
|
119
|
-
'type == "たいやき"',
|
120
|
-
'type == "和菓子"',
|
121
|
-
'keyword @ "たいやき"',
|
122
|
-
'keyword @ "白"',
|
123
|
-
'keyword @ "養殖"'],
|
124
|
-
select.conditions)
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_to_uri_format
|
128
|
-
filter = 'geo_in_rectangle(location,' +
|
129
|
-
'"35.73360x139.7394","62614x139.7714") && ' +
|
130
|
-
'((type == "たいやき" || type == "和菓子")) && ' +
|
131
|
-
'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
|
132
|
-
select = parse("select",
|
133
|
-
:table => "Users",
|
134
|
-
:filter => filter)
|
135
|
-
assert_equal("/d/select.json?filter=geo_in_rectangle%28location%2C" +
|
136
|
-
"%2235.73360x139.7394%22%2C%2262614x139.7714%22%29+" +
|
137
|
-
"%26%26+%28%28type+" +
|
138
|
-
"%3D%3D+%22%E3%81%9F%E3%81%84%E3%82%84%E3%81%8D%22+" +
|
139
|
-
"%7C%7C+type+%3D%3D+" +
|
140
|
-
"%22%E5%92%8C%E8%8F%93%E5%AD%90%22%29%29+" +
|
141
|
-
"%26%26+keyword+%40+" +
|
142
|
-
"%22%E3%81%9F%E3%81%84%E3%82%84%E3%81%8D%22+%26%21+" +
|
143
|
-
"keyword+%40+%22%E7%99%BD%22+%26%21+" +
|
144
|
-
"keyword+%40+%22%E9%A4%8A%E6%AE%96%22&table=Users",
|
145
|
-
select.to_uri_format)
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_to_command_format
|
149
|
-
filter = 'geo_in_rectangle(location,' +
|
150
|
-
'"35.73360x139.7394","62614x139.7714") && ' +
|
151
|
-
'((type == "たいやき" || type == "和菓子")) && ' +
|
152
|
-
'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
|
153
|
-
select = parse("select",
|
154
|
-
:table => "Users",
|
155
|
-
:filter => filter)
|
156
|
-
assert_equal("select " +
|
157
|
-
"--filter " +
|
158
|
-
"\"geo_in_rectangle(location," +
|
159
|
-
"\\\"35.73360x139.7394\\\",\\\"62614x139.7714\\\") && " +
|
160
|
-
"((type == \\\"たいやき\\\" || " +
|
161
|
-
"type == \\\"和菓子\\\")) && " +
|
162
|
-
"keyword @ \\\"たいやき\\\" &! keyword @ \\\"白\\\" &! " +
|
163
|
-
"keyword @ \\\"養殖\\\"\" " +
|
164
|
-
"--output_type \"json\" --table \"Users\"",
|
165
|
-
select.to_command_format)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
class HTTPSelectCommandParseTest < Test::Unit::TestCase
|
170
|
-
include SelectCommandParseTests
|
171
|
-
include SelectCommandParseFilterTests
|
172
|
-
include HTTPCommandParseTestUtils
|
173
|
-
|
174
|
-
def test_uri_format?
|
175
|
-
command = parse("status")
|
176
|
-
assert_predicate(command, :uri_format?)
|
177
|
-
end
|
178
|
-
|
179
|
-
def test_command_format?
|
180
|
-
command = parse("status")
|
181
|
-
assert_not_predicate(command, :command_format?)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class CommandLineSelecCommandParseTest < Test::Unit::TestCase
|
186
|
-
include SelectCommandParseTests
|
187
|
-
include SelectCommandParseFilterTests
|
188
|
-
include CommandLineCommandParseTestUtils
|
189
|
-
|
190
|
-
def test_uri_format?
|
191
|
-
command = parse("status")
|
192
|
-
assert_not_predicate(command, :uri_format?)
|
193
|
-
end
|
194
|
-
|
195
|
-
def test_command_format?
|
196
|
-
command = parse("status")
|
197
|
-
assert_predicate(command, :command_format?)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
class StatisticOperationParseTest < Test::Unit::TestCase
|
202
|
-
def test_context
|
203
|
-
operations = statistics.first.operations.collect do |operation|
|
204
|
-
[operation[:name], operation[:context]]
|
205
|
-
end
|
206
|
-
expected = [
|
207
|
-
["filter", "local_name @ \"gsub\""],
|
208
|
-
["filter", "description @ \"string\""],
|
209
|
-
["select", nil],
|
210
|
-
["sort", "_score"],
|
211
|
-
["output", "_key"],
|
212
|
-
["drilldown", "name"],
|
213
|
-
["drilldown", "class"],
|
214
|
-
]
|
215
|
-
assert_equal(expected, operations)
|
216
|
-
end
|
217
|
-
|
218
|
-
def test_n_records
|
219
|
-
operations = statistics.first.operations.collect do |operation|
|
220
|
-
[operation[:name], operation[:n_records]]
|
221
|
-
end
|
222
|
-
expected = [
|
223
|
-
["filter", 15],
|
224
|
-
["filter", 13],
|
225
|
-
["select", 13],
|
226
|
-
["sort", 10],
|
227
|
-
["output", 10],
|
228
|
-
["drilldown", 3],
|
229
|
-
["drilldown", 2],
|
230
|
-
]
|
231
|
-
assert_equal(expected, operations)
|
232
|
-
end
|
233
|
-
|
234
|
-
private
|
235
|
-
def log
|
236
|
-
<<-EOL
|
237
|
-
2011-06-02 16:27:04.731685|5091e5c0|>/d/select.join?table=Entries&filter=local_name+%40+%22gsub%22+%26%26+description+%40+%22string%22&sortby=_score&output_columns=_key&drilldown=name,class
|
238
|
-
2011-06-02 16:27:04.733539|5091e5c0|:000000001849451 filter(15)
|
239
|
-
2011-06-02 16:27:04.734978|5091e5c0|:000000003293459 filter(13)
|
240
|
-
2011-06-02 16:27:04.735012|5091e5c0|:000000003327415 select(13)
|
241
|
-
2011-06-02 16:27:04.735096|5091e5c0|:000000003411824 sort(10)
|
242
|
-
2011-06-02 16:27:04.735232|5091e5c0|:000000003547265 output(10)
|
243
|
-
2011-06-02 16:27:04.735606|5091e5c0|:000000003921419 drilldown(3)
|
244
|
-
2011-06-02 16:27:04.735762|5091e5c0|:000000004077552 drilldown(2)
|
245
|
-
2011-06-02 16:27:04.735808|5091e5c0|<000000004123726 rc=0
|
246
|
-
EOL
|
247
|
-
end
|
248
|
-
|
249
|
-
def statistics
|
250
|
-
statistics = []
|
251
|
-
parser = Groonga::QueryLog::Parser.new
|
252
|
-
parser.parse(StringIO.new(log)) do |statistic|
|
253
|
-
statistics << statistic
|
254
|
-
end
|
255
|
-
statistics
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|