rroonga 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -211,13 +211,31 @@ VALUE
211
211
  rb_grn_context_rb_string_encode (grn_ctx *context, VALUE rb_string)
212
212
  {
213
213
  #ifdef HAVE_RUBY_ENCODING_H
214
- rb_encoding *encoding, *to_encode;
214
+ int index, to_index;
215
+ rb_encoding *encoding, *to_encoding;
216
+ grn_encoding context_encoding;
217
+
218
+ context_encoding = context->encoding;
219
+ if (context->encoding == GRN_ENC_DEFAULT)
220
+ context->encoding = grn_get_default_encoding();
221
+ if (context->encoding == GRN_ENC_NONE)
222
+ return rb_string;
223
+
224
+ if (RSTRING_LEN(rb_string) < 0)
225
+ return rb_string;
215
226
 
216
227
  encoding = rb_enc_get(rb_string);
217
- to_encode = rb_grn_encoding_to_ruby_encoding(context->encoding);
218
- if (rb_enc_to_index(encoding) != rb_enc_to_index(to_encode))
219
- rb_string = rb_str_encode(rb_string, rb_enc_from_encoding(to_encode),
220
- 0, Qnil);
228
+ to_encoding = rb_grn_encoding_to_ruby_encoding(context_encoding);
229
+ index = rb_enc_to_index(encoding);
230
+ to_index = rb_enc_to_index(to_encoding);
231
+ if (index == to_index)
232
+ return rb_string;
233
+
234
+ if (rb_enc_asciicompat(to_encoding) && rb_enc_str_asciionly_p(rb_string))
235
+ return rb_string;
236
+
237
+ rb_string = rb_str_encode(rb_string, rb_enc_from_encoding(to_encoding),
238
+ 0, Qnil);
221
239
  #endif
222
240
  return rb_string;
223
241
  }
@@ -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
@@ -453,11 +453,7 @@ rb_grn_index_column_search (int argc, VALUE *argv, VALUE self)
453
453
 
454
454
  rb_scan_args(argc, argv, "11", &rb_query, &options);
455
455
 
456
- if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cGrnQuery))) {
457
- grn_query *_query;
458
- _query = RVAL2GRNQUERY(rb_query);
459
- query = (grn_obj *)_query;
460
- } else if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cInteger))) {
456
+ if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cInteger))) {
461
457
  grn_id id;
462
458
  id = NUM2UINT(rb_query);
463
459
  GRN_TEXT_SET(context, id_query, &id, sizeof(grn_id));
@@ -1,6 +1,6 @@
1
1
  /* -*- coding: utf-8; c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2011 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
@@ -20,6 +20,36 @@
20
20
 
21
21
  VALUE rb_mGrnOperator;
22
22
 
23
+ grn_operator
24
+ rb_grn_operator_from_ruby_object (VALUE rb_operator)
25
+ {
26
+ grn_operator operator = GRN_OP_OR;
27
+
28
+ if (NIL_P(rb_operator) ||
29
+ rb_grn_equal_option(rb_operator, "or") ||
30
+ rb_grn_equal_option(rb_operator, "||")) {
31
+ operator = GRN_OP_OR;
32
+ } else if (rb_grn_equal_option(rb_operator, "and") ||
33
+ rb_grn_equal_option(rb_operator, "+") ||
34
+ rb_grn_equal_option(rb_operator, "&&")) {
35
+ operator = GRN_OP_AND;
36
+ } else if (rb_grn_equal_option(rb_operator, "but") ||
37
+ rb_grn_equal_option(rb_operator, "not") ||
38
+ rb_grn_equal_option(rb_operator, "-")) {
39
+ operator = GRN_OP_BUT;
40
+ } else if (rb_grn_equal_option(rb_operator, "adjust") ||
41
+ rb_grn_equal_option(rb_operator, ">")) {
42
+ operator = GRN_OP_ADJUST;
43
+ } else {
44
+ rb_raise(rb_eArgError,
45
+ "operator should be one of "
46
+ "[:or, :||, :and, :+, :&&, :but, :not, :-, :adjust, :>]: <%s>",
47
+ rb_grn_inspect(rb_operator));
48
+ }
49
+
50
+ return operator;
51
+ }
52
+
23
53
  void
24
54
  rb_grn_init_operator (VALUE mGrn)
25
55
  {
@@ -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-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
@@ -28,6 +28,80 @@ VALUE rb_cGrnVariableSizeColumn;
28
28
  * 可変長データ用のカラム。
29
29
  */
30
30
 
31
+ /*
32
+ * Document-method: compressed?
33
+ *
34
+ * call-seq:
35
+ * column.compressed? -> boolean
36
+ * column.compressed?(type) -> boolean
37
+ *
38
+ * Returns whether the column is compressed or not. If
39
+ * @type@ is specified, it returns whether the column is
40
+ * compressed by @type@ or not.
41
+ *
42
+ * @return [Boolean] whether the column is compressed or not.
43
+ * @param [:zlib, :lzo] type (nil) If @type@ isn't @nil@,
44
+ * it checks whether specified compressed type is used or
45
+ * not.
46
+ * @since 1.3.1
47
+ */
48
+ static VALUE
49
+ rb_grn_variable_size_column_compressed_p (int argc, VALUE *argv, VALUE self)
50
+ {
51
+ RbGrnColumn *rb_grn_column;
52
+ grn_ctx *context = NULL;
53
+ grn_obj *column;
54
+ grn_obj_flags flags;
55
+ VALUE type;
56
+ grn_bool compressed_p = GRN_FALSE;
57
+ grn_bool accept_any_type = GRN_FALSE;
58
+ grn_bool need_zlib_check = GRN_FALSE;
59
+ grn_bool need_lzo_check = GRN_FALSE;
60
+
61
+ rb_scan_args(argc, argv, "01", &type);
62
+
63
+ if (NIL_P(type)) {
64
+ accept_any_type = GRN_TRUE;
65
+ } else {
66
+ if (rb_grn_equal_option(type, "zlib")) {
67
+ need_zlib_check = GRN_TRUE;
68
+ } else if (rb_grn_equal_option(type, "lzo")) {
69
+ need_lzo_check = GRN_TRUE;
70
+ } else {
71
+ rb_raise(rb_eArgError,
72
+ "compressed type should be <:zlib> or <:lzo>: <%s>",
73
+ rb_grn_inspect(type));
74
+ }
75
+ }
76
+
77
+ rb_grn_column = SELF(self);
78
+ rb_grn_object_deconstruct(RB_GRN_OBJECT(rb_grn_column), &column, &context,
79
+ NULL, NULL,
80
+ NULL, NULL);
81
+
82
+ flags = column->header.flags;
83
+ switch (flags & GRN_OBJ_COMPRESS_MASK) {
84
+ case GRN_OBJ_COMPRESS_ZLIB:
85
+ if (accept_any_type || need_zlib_check) {
86
+ grn_obj support_p;
87
+ GRN_BOOL_INIT(&support_p, 0);
88
+ grn_obj_get_info(context, NULL, GRN_INFO_SUPPORT_ZLIB, &support_p);
89
+ compressed_p = GRN_BOOL_VALUE(&support_p);
90
+ }
91
+ break;
92
+ case GRN_OBJ_COMPRESS_LZO:
93
+ if (accept_any_type || need_lzo_check) {
94
+ grn_obj support_p;
95
+ GRN_BOOL_INIT(&support_p, 0);
96
+ grn_obj_get_info(context, NULL, GRN_INFO_SUPPORT_LZO, &support_p);
97
+ compressed_p = GRN_BOOL_VALUE(&support_p);
98
+ }
99
+ break;
100
+ }
101
+
102
+ return CBOOL2RVAL(compressed_p);
103
+ }
104
+
31
105
  /*
32
106
  * Document-method: defrag
33
107
  *
@@ -77,6 +151,8 @@ rb_grn_init_variable_size_column (VALUE mGrn)
77
151
  rb_cGrnVariableSizeColumn =
78
152
  rb_define_class_under(mGrn, "VariableSizeColumn", rb_cGrnColumn);
79
153
 
154
+ rb_define_method(rb_cGrnVariableSizeColumn, "compressed?",
155
+ rb_grn_variable_size_column_compressed_p, -1);
80
156
  rb_define_method(rb_cGrnVariableSizeColumn, "defrag",
81
157
  rb_grn_variable_size_column_defrag, -1);
82
158
  }
data/ext/groonga/rb-grn.h CHANGED
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2011 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
@@ -72,7 +72,7 @@ RB_GRN_BEGIN_DECLS
72
72
 
73
73
  #define RB_GRN_MAJOR_VERSION 1
74
74
  #define RB_GRN_MINOR_VERSION 3
75
- #define RB_GRN_MICRO_VERSION 0
75
+ #define RB_GRN_MICRO_VERSION 1
76
76
 
77
77
  #define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
78
78
 
@@ -227,7 +227,6 @@ RB_GRN_VAR VALUE rb_cGrnAccessor;
227
227
  RB_GRN_VAR VALUE rb_cGrnViewAccessor;
228
228
  RB_GRN_VAR VALUE rb_cGrnRecord;
229
229
  RB_GRN_VAR VALUE rb_cGrnViewRecord;
230
- RB_GRN_VAR VALUE rb_cGrnQuery;
231
230
  RB_GRN_VAR VALUE rb_cGrnLogger;
232
231
  RB_GRN_VAR VALUE rb_cGrnSnippet;
233
232
  RB_GRN_VAR VALUE rb_cGrnVariable;
@@ -270,7 +269,6 @@ void rb_grn_init_accessor (VALUE mGrn);
270
269
  void rb_grn_init_view_accessor (VALUE mGrn);
271
270
  void rb_grn_init_record (VALUE mGrn);
272
271
  void rb_grn_init_view_record (VALUE mGrn);
273
- void rb_grn_init_query (VALUE mGrn);
274
272
  void rb_grn_init_variable (VALUE mGrn);
275
273
  void rb_grn_init_operator (VALUE mGrn);
276
274
  void rb_grn_init_expression (VALUE mGrn);
@@ -555,9 +553,6 @@ VALUE rb_grn_column_expression_builder_build
555
553
  #define GRNACCESSOR2RVAL(context, accessor, owner) \
556
554
  (rb_grn_accessor_to_ruby_object(context, accessor, owner))
557
555
 
558
- #define RVAL2GRNQUERY(object) (rb_grn_query_from_ruby_object(object))
559
- #define GRNQUERY2RVAL(context, column)(rb_grn_query_to_ruby_object(context, column))
560
-
561
556
  #define RVAL2GRNOPERATOR(object) (rb_grn_operator_from_ruby_object(object))
562
557
 
563
558
  #define RVAL2GRNLOGGER(object) (rb_grn_logger_from_ruby_object(object))
@@ -665,10 +660,6 @@ VALUE rb_grn_index_cursor_to_ruby_object (grn_ctx *context,
665
660
  grn_obj *cursor,
666
661
  grn_bool owner);
667
662
 
668
- grn_query *rb_grn_query_from_ruby_object (VALUE object);
669
- VALUE rb_grn_query_to_ruby_object (grn_ctx *context,
670
- grn_query *query);
671
-
672
663
  grn_operator rb_grn_operator_from_ruby_object (VALUE object);
673
664
 
674
665
  grn_logger_info *
@@ -1,6 +1,6 @@
1
1
  /* -*- coding: utf-8; c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2011 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
@@ -138,7 +138,6 @@ Init_groonga (void)
138
138
  rb_grn_init_view_accessor(mGrn);
139
139
  rb_grn_init_record(mGrn);
140
140
  rb_grn_init_view_record(mGrn);
141
- rb_grn_init_query(mGrn);
142
141
  rb_grn_init_variable(mGrn);
143
142
  rb_grn_init_operator(mGrn);
144
143
  rb_grn_init_expression(mGrn);
@@ -0,0 +1,169 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 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
+ module Groonga
19
+ module Command
20
+ class Builder
21
+ class << self
22
+ def escape_value(value)
23
+ escaped_value = value.to_s.gsub(/"/, '\\"')
24
+ "\"#{escaped_value}\""
25
+ end
26
+ end
27
+
28
+ attr_reader :command, :arguments
29
+ def initialize(command, arguments={})
30
+ @command = command
31
+ @arguments = arguments
32
+ end
33
+
34
+ def [](key)
35
+ @arguments[key]
36
+ end
37
+
38
+ def []=(key, value)
39
+ @arguments[key] = value
40
+ end
41
+
42
+ def build
43
+ query = "#{@command} "
44
+ @arguments.each do |key, value|
45
+ value = value.join(", ") if value.is_a?(::Array)
46
+ escaped_value = self.class.escape_value(value)
47
+ query << " --#{key} #{escaped_value}"
48
+ end
49
+ query
50
+ end
51
+ end
52
+
53
+ class Select
54
+ def initialize(context, table, options)
55
+ @context = context
56
+ @table = table
57
+ @options = normalize_options(options)
58
+ end
59
+
60
+ def exec
61
+ request_id = @context.send(query)
62
+ loop do
63
+ response_id, result = @context.receive
64
+ if request_id == response_id
65
+ drill_down_keys = @options["drilldown"]
66
+ if drill_down_keys.is_a?(String)
67
+ drill_down_keys = drill_down_keys.split(/(?:\s+|\s*,\s*)/)
68
+ end
69
+ return Result.parse(result, drill_down_keys)
70
+ end
71
+ # raise if request_id < response_id
72
+ end
73
+ end
74
+
75
+ private
76
+ def normalize_options(options)
77
+ normalized_options = {}
78
+ options.each do |key, value|
79
+ normalized_options[normalize_option_name(key)] = value
80
+ end
81
+ normalized_options
82
+ end
83
+
84
+ def normalize_option_name(name)
85
+ name = name.to_s.gsub(/-/, "_").gsub(/drill_down/, "drilldown")
86
+ name.gsub(/sort_by/, 'sortby')
87
+ end
88
+
89
+ def query
90
+ if @table.is_a?(String)
91
+ table_name = @table
92
+ else
93
+ table_name = @table.name
94
+ end
95
+ builder = Builder.new("select", @options.merge(:table => table_name))
96
+ builder.build
97
+ end
98
+
99
+ class Result < Struct.new(:n_hits, :columns, :values, :drill_down)
100
+ class << self
101
+ def parse(json, drill_down_keys)
102
+ select_result, *drill_down_results = JSON.parse(json)
103
+ result = new
104
+ n_hits, columns, values = extract_result(select_result)
105
+ result.n_hits = n_hits
106
+ result.columns = columns
107
+ result.values = values
108
+ if drill_down_results
109
+ result.drill_down = parse_drill_down_results(drill_down_results,
110
+ drill_down_keys)
111
+ end
112
+ result
113
+ end
114
+
115
+ def create_records(columns, values)
116
+ records = []
117
+ values.each do |value|
118
+ record = {}
119
+ columns.each_with_index do |(name, type), i|
120
+ record[name] = convert_value(value[i], type)
121
+ end
122
+ records << record
123
+ end
124
+ records
125
+ end
126
+
127
+ private
128
+ def parse_drill_down_results(results, keys)
129
+ named_results = {}
130
+ results.each_with_index do |drill_down, i|
131
+ n_hits, columns, values = extract_result(drill_down)
132
+ drill_down_result = DrillDownResult.new
133
+ drill_down_result.n_hits = n_hits
134
+ drill_down_result.columns = columns
135
+ drill_down_result.values = values
136
+ named_results[keys[i]] = drill_down_result
137
+ end
138
+ named_results
139
+ end
140
+
141
+ def extract_result(result)
142
+ meta_data, columns, *values = result
143
+ n_hits, = meta_data
144
+ [n_hits, columns, values]
145
+ end
146
+
147
+ def convert_value(value, type)
148
+ case type
149
+ when "Time"
150
+ Time.at(value)
151
+ else
152
+ value
153
+ end
154
+ end
155
+ end
156
+
157
+ def records
158
+ @records ||= self.class.create_records(columns, values)
159
+ end
160
+
161
+ class DrillDownResult < Struct.new(:n_hits, :columns, :values)
162
+ def records
163
+ @records ||= Result.create_records(columns, values)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2010-2011 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-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
@@ -15,6 +15,8 @@
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 "groonga/command"
19
+
18
20
  module Groonga
19
21
  class Context
20
22
  # _path_ にある既存のデータベースを開く。ブロックを指定した場
@@ -70,130 +72,8 @@ module Groonga
70
72
  # @option options [Array] XXX TODO
71
73
  # TODO
72
74
  def select(table, options={})
73
- select = SelectCommand.new(self, table, options)
75
+ select = Command::Select.new(self, table, options)
74
76
  select.exec
75
77
  end
76
-
77
- class SelectResult < Struct.new(:n_hits, :columns, :values,
78
- :drill_down)
79
- class << self
80
- def parse(json, drill_down_keys)
81
- select_result, *drill_down_results = JSON.parse(json)
82
- result = new
83
- n_hits, columns, values = extract_result(select_result)
84
- result.n_hits = n_hits
85
- result.columns = columns
86
- result.values = values
87
- if drill_down_results
88
- result.drill_down = parse_drill_down_results(drill_down_results,
89
- drill_down_keys)
90
- end
91
- result
92
- end
93
-
94
- def create_records(columns, values)
95
- records = []
96
- values.each do |value|
97
- record = {}
98
- columns.each_with_index do |(name, type), i|
99
- record[name] = convert_value(value[i], type)
100
- end
101
- records << record
102
- end
103
- records
104
- end
105
-
106
- private
107
- def parse_drill_down_results(results, keys)
108
- named_results = {}
109
- results.each_with_index do |drill_down, i|
110
- n_hits, columns, values = extract_result(drill_down)
111
- drill_down_result = DrillDownResult.new
112
- drill_down_result.n_hits = n_hits
113
- drill_down_result.columns = columns
114
- drill_down_result.values = values
115
- named_results[keys[i]] = drill_down_result
116
- end
117
- named_results
118
- end
119
-
120
- def extract_result(result)
121
- meta_data, columns, *values = result
122
- n_hits, = meta_data
123
- [n_hits, columns, values]
124
- end
125
-
126
- def convert_value(value, type)
127
- case type
128
- when "Time"
129
- Time.at(value)
130
- else
131
- value
132
- end
133
- end
134
- end
135
-
136
- def records
137
- @records ||= self.class.create_records(columns, values)
138
- end
139
-
140
- class DrillDownResult < Struct.new(:n_hits, :columns, :values)
141
- def records
142
- @records ||= SelectResult.create_records(columns, values)
143
- end
144
- end
145
- end
146
-
147
- class SelectCommand
148
- def initialize(context, table, options)
149
- @context = context
150
- @table = table
151
- @options = normalize_options(options)
152
- end
153
-
154
- def exec
155
- request_id = @context.send(query)
156
- loop do
157
- response_id, result = @context.receive
158
- if request_id == response_id
159
- drill_down_keys = @options["drilldown"]
160
- if drill_down_keys.is_a?(String)
161
- drill_down_keys = drill_down_keys.split(/(?:\s+|\s*,\s*)/)
162
- end
163
- return SelectResult.parse(result, drill_down_keys)
164
- end
165
- # raise if request_id < response_id
166
- end
167
- end
168
-
169
- private
170
- def normalize_options(options)
171
- normalized_options = {}
172
- options.each do |key, value|
173
- normalized_options[normalize_option_name(key)] = value
174
- end
175
- normalized_options
176
- end
177
-
178
- def normalize_option_name(name)
179
- name = name.to_s.gsub(/-/, "_").gsub(/drill_down/, "drilldown")
180
- name.gsub(/sort_by/, 'sortby')
181
- end
182
-
183
- def query
184
- if @table.is_a?(String)
185
- table_name = @table
186
- else
187
- table_name = @table.name
188
- end
189
- _query = "select #{table_name}"
190
- @options.each do |key, value|
191
- value = value.join(", ") if value.is_a?(::Array)
192
- escaped_value = value.to_s.gsub(/"/, '\\"')
193
- _query << " --#{key} \"#{escaped_value}\""
194
- end
195
- _query
196
- end
197
- end
198
78
  end
199
79
  end