ferret 0.11.6 → 0.11.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/README +10 -22
  2. data/RELEASE_CHANGES +137 -0
  3. data/RELEASE_NOTES +60 -0
  4. data/Rakefile +379 -274
  5. data/TODO +100 -8
  6. data/bin/ferret-browser +0 -0
  7. data/ext/BZLIB_blocksort.c +1094 -0
  8. data/ext/BZLIB_bzlib.c +1578 -0
  9. data/ext/BZLIB_compress.c +672 -0
  10. data/ext/BZLIB_crctable.c +104 -0
  11. data/ext/BZLIB_decompress.c +626 -0
  12. data/ext/BZLIB_huffman.c +205 -0
  13. data/ext/BZLIB_randtable.c +84 -0
  14. data/ext/{api.c → STEMMER_api.c} +7 -10
  15. data/ext/{libstemmer.c → STEMMER_libstemmer.c} +3 -2
  16. data/ext/{stem_ISO_8859_1_danish.c → STEMMER_stem_ISO_8859_1_danish.c} +123 -124
  17. data/ext/{stem_ISO_8859_1_dutch.c → STEMMER_stem_ISO_8859_1_dutch.c} +177 -188
  18. data/ext/STEMMER_stem_ISO_8859_1_english.c +1117 -0
  19. data/ext/{stem_ISO_8859_1_finnish.c → STEMMER_stem_ISO_8859_1_finnish.c} +276 -306
  20. data/ext/STEMMER_stem_ISO_8859_1_french.c +1246 -0
  21. data/ext/{stem_ISO_8859_1_german.c → STEMMER_stem_ISO_8859_1_german.c} +161 -170
  22. data/ext/STEMMER_stem_ISO_8859_1_hungarian.c +1230 -0
  23. data/ext/STEMMER_stem_ISO_8859_1_italian.c +1065 -0
  24. data/ext/STEMMER_stem_ISO_8859_1_norwegian.c +297 -0
  25. data/ext/{stem_ISO_8859_1_porter.c → STEMMER_stem_ISO_8859_1_porter.c} +263 -290
  26. data/ext/{stem_ISO_8859_1_portuguese.c → STEMMER_stem_ISO_8859_1_portuguese.c} +362 -380
  27. data/ext/STEMMER_stem_ISO_8859_1_spanish.c +1093 -0
  28. data/ext/STEMMER_stem_ISO_8859_1_swedish.c +307 -0
  29. data/ext/STEMMER_stem_ISO_8859_2_romanian.c +998 -0
  30. data/ext/{stem_KOI8_R_russian.c → STEMMER_stem_KOI8_R_russian.c} +244 -245
  31. data/ext/STEMMER_stem_UTF_8_danish.c +339 -0
  32. data/ext/{stem_UTF_8_dutch.c → STEMMER_stem_UTF_8_dutch.c} +192 -211
  33. data/ext/STEMMER_stem_UTF_8_english.c +1125 -0
  34. data/ext/{stem_UTF_8_finnish.c → STEMMER_stem_UTF_8_finnish.c} +284 -324
  35. data/ext/STEMMER_stem_UTF_8_french.c +1256 -0
  36. data/ext/{stem_UTF_8_german.c → STEMMER_stem_UTF_8_german.c} +170 -187
  37. data/ext/STEMMER_stem_UTF_8_hungarian.c +1234 -0
  38. data/ext/STEMMER_stem_UTF_8_italian.c +1073 -0
  39. data/ext/STEMMER_stem_UTF_8_norwegian.c +299 -0
  40. data/ext/{stem_UTF_8_porter.c → STEMMER_stem_UTF_8_porter.c} +271 -310
  41. data/ext/STEMMER_stem_UTF_8_portuguese.c +1023 -0
  42. data/ext/STEMMER_stem_UTF_8_romanian.c +1004 -0
  43. data/ext/STEMMER_stem_UTF_8_russian.c +694 -0
  44. data/ext/STEMMER_stem_UTF_8_spanish.c +1097 -0
  45. data/ext/STEMMER_stem_UTF_8_swedish.c +309 -0
  46. data/ext/STEMMER_stem_UTF_8_turkish.c +2205 -0
  47. data/ext/{utilities.c → STEMMER_utilities.c} +100 -68
  48. data/ext/analysis.c +276 -121
  49. data/ext/analysis.h +190 -143
  50. data/ext/api.h +3 -4
  51. data/ext/array.c +5 -3
  52. data/ext/array.h +52 -43
  53. data/ext/bitvector.c +38 -482
  54. data/ext/bitvector.h +446 -124
  55. data/ext/bzlib.h +282 -0
  56. data/ext/bzlib_private.h +503 -0
  57. data/ext/compound_io.c +23 -22
  58. data/ext/config.h +21 -11
  59. data/ext/document.c +43 -40
  60. data/ext/document.h +31 -21
  61. data/ext/except.c +20 -38
  62. data/ext/except.h +89 -76
  63. data/ext/extconf.rb +3 -2
  64. data/ext/ferret.c +49 -35
  65. data/ext/ferret.h +14 -11
  66. data/ext/field_index.c +262 -0
  67. data/ext/field_index.h +52 -0
  68. data/ext/filter.c +11 -10
  69. data/ext/fs_store.c +65 -47
  70. data/ext/global.c +245 -165
  71. data/ext/global.h +252 -54
  72. data/ext/hash.c +200 -243
  73. data/ext/hash.h +205 -163
  74. data/ext/hashset.c +118 -96
  75. data/ext/hashset.h +110 -82
  76. data/ext/header.h +19 -19
  77. data/ext/helper.c +11 -10
  78. data/ext/helper.h +14 -6
  79. data/ext/index.c +745 -366
  80. data/ext/index.h +503 -529
  81. data/ext/internal.h +1020 -0
  82. data/ext/lang.c +10 -0
  83. data/ext/lang.h +35 -15
  84. data/ext/mempool.c +5 -4
  85. data/ext/mempool.h +30 -22
  86. data/ext/modules.h +35 -7
  87. data/ext/multimapper.c +43 -2
  88. data/ext/multimapper.h +32 -23
  89. data/ext/posh.c +0 -0
  90. data/ext/posh.h +4 -38
  91. data/ext/priorityqueue.c +10 -12
  92. data/ext/priorityqueue.h +33 -21
  93. data/ext/q_boolean.c +22 -9
  94. data/ext/q_const_score.c +3 -2
  95. data/ext/q_filtered_query.c +15 -12
  96. data/ext/q_fuzzy.c +147 -135
  97. data/ext/q_match_all.c +3 -2
  98. data/ext/q_multi_term.c +28 -32
  99. data/ext/q_parser.c +451 -173
  100. data/ext/q_phrase.c +158 -79
  101. data/ext/q_prefix.c +16 -18
  102. data/ext/q_range.c +363 -31
  103. data/ext/q_span.c +130 -141
  104. data/ext/q_term.c +21 -21
  105. data/ext/q_wildcard.c +19 -23
  106. data/ext/r_analysis.c +369 -242
  107. data/ext/r_index.c +421 -434
  108. data/ext/r_qparser.c +142 -92
  109. data/ext/r_search.c +790 -407
  110. data/ext/r_store.c +44 -44
  111. data/ext/r_utils.c +264 -96
  112. data/ext/ram_store.c +29 -23
  113. data/ext/scanner.c +895 -0
  114. data/ext/scanner.h +36 -0
  115. data/ext/scanner_mb.c +6701 -0
  116. data/ext/scanner_utf8.c +4415 -0
  117. data/ext/search.c +210 -87
  118. data/ext/search.h +556 -488
  119. data/ext/similarity.c +17 -16
  120. data/ext/similarity.h +51 -44
  121. data/ext/sort.c +157 -354
  122. data/ext/stem_ISO_8859_1_hungarian.h +16 -0
  123. data/ext/stem_ISO_8859_2_romanian.h +16 -0
  124. data/ext/stem_UTF_8_hungarian.h +16 -0
  125. data/ext/stem_UTF_8_romanian.h +16 -0
  126. data/ext/stem_UTF_8_turkish.h +16 -0
  127. data/ext/stopwords.c +287 -278
  128. data/ext/store.c +57 -51
  129. data/ext/store.h +308 -286
  130. data/ext/symbol.c +10 -0
  131. data/ext/symbol.h +23 -0
  132. data/ext/term_vectors.c +14 -293
  133. data/ext/threading.h +22 -22
  134. data/ext/win32.h +12 -4
  135. data/lib/ferret.rb +2 -1
  136. data/lib/ferret/browser.rb +1 -1
  137. data/lib/ferret/field_symbol.rb +94 -0
  138. data/lib/ferret/index.rb +221 -34
  139. data/lib/ferret/number_tools.rb +6 -6
  140. data/lib/ferret/version.rb +3 -0
  141. data/test/{unit → long_running}/largefile/tc_largefile.rb +1 -1
  142. data/test/test_helper.rb +7 -2
  143. data/test/test_installed.rb +1 -0
  144. data/test/threading/thread_safety_index_test.rb +10 -1
  145. data/test/threading/thread_safety_read_write_test.rb +4 -7
  146. data/test/threading/thread_safety_test.rb +0 -0
  147. data/test/unit/analysis/tc_analyzer.rb +29 -27
  148. data/test/unit/analysis/tc_token_stream.rb +23 -16
  149. data/test/unit/index/tc_index.rb +116 -11
  150. data/test/unit/index/tc_index_reader.rb +27 -27
  151. data/test/unit/index/tc_index_writer.rb +10 -0
  152. data/test/unit/index/th_doc.rb +38 -21
  153. data/test/unit/search/tc_filter.rb +31 -10
  154. data/test/unit/search/tc_index_searcher.rb +6 -0
  155. data/test/unit/search/tm_searcher.rb +53 -1
  156. data/test/unit/store/tc_fs_store.rb +40 -2
  157. data/test/unit/store/tc_ram_store.rb +0 -0
  158. data/test/unit/store/tm_store.rb +0 -0
  159. data/test/unit/store/tm_store_lock.rb +7 -6
  160. data/test/unit/tc_field_symbol.rb +26 -0
  161. data/test/unit/ts_analysis.rb +0 -0
  162. data/test/unit/ts_index.rb +0 -0
  163. data/test/unit/ts_store.rb +0 -0
  164. data/test/unit/ts_utils.rb +0 -0
  165. data/test/unit/utils/tc_number_tools.rb +0 -0
  166. data/test/utils/content_generator.rb +226 -0
  167. metadata +262 -221
  168. data/ext/inc/lang.h +0 -48
  169. data/ext/inc/threading.h +0 -31
  170. data/ext/stem_ISO_8859_1_english.c +0 -1156
  171. data/ext/stem_ISO_8859_1_french.c +0 -1276
  172. data/ext/stem_ISO_8859_1_italian.c +0 -1091
  173. data/ext/stem_ISO_8859_1_norwegian.c +0 -296
  174. data/ext/stem_ISO_8859_1_spanish.c +0 -1119
  175. data/ext/stem_ISO_8859_1_swedish.c +0 -307
  176. data/ext/stem_UTF_8_danish.c +0 -344
  177. data/ext/stem_UTF_8_english.c +0 -1176
  178. data/ext/stem_UTF_8_french.c +0 -1296
  179. data/ext/stem_UTF_8_italian.c +0 -1113
  180. data/ext/stem_UTF_8_norwegian.c +0 -302
  181. data/ext/stem_UTF_8_portuguese.c +0 -1055
  182. data/ext/stem_UTF_8_russian.c +0 -709
  183. data/ext/stem_UTF_8_spanish.c +0 -1137
  184. data/ext/stem_UTF_8_swedish.c +0 -313
  185. data/lib/ferret_version.rb +0 -3
@@ -1,3 +1,4 @@
1
+ #include "symbol.h"
1
2
  #include "ferret.h"
2
3
  #include "search.h"
3
4
 
@@ -17,10 +18,11 @@ static VALUE sym_handle_parse_errors;
17
18
  static VALUE sym_clean_string;
18
19
  static VALUE sym_max_clauses;
19
20
  static VALUE sym_use_keywords;
21
+ static VALUE sym_use_typed_range_query;
20
22
 
21
- extern VALUE frt_get_analyzer(Analyzer *a);
22
- extern VALUE frt_get_q(Query *q);
23
- extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
23
+ extern VALUE frb_get_analyzer(Analyzer *a);
24
+ extern VALUE frb_get_q(Query *q);
25
+ extern Analyzer *frb_get_cwrapped_analyzer(VALUE ranalyzer);
24
26
 
25
27
  /****************************************************************************
26
28
  *
@@ -29,20 +31,20 @@ extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
29
31
  ****************************************************************************/
30
32
 
31
33
  static void
32
- frt_qp_free(void *p)
34
+ frb_qp_free(void *p)
33
35
  {
34
36
  object_del(p);
35
37
  qp_destroy((QParser *)p);
36
38
  }
37
39
 
38
40
  static void
39
- frt_qp_mark(void *p)
41
+ frb_qp_mark(void *p)
40
42
  {
41
- frt_gc_mark(((QParser *)p)->analyzer);
43
+ frb_gc_mark(((QParser *)p)->analyzer);
42
44
  }
43
45
 
44
46
  static HashSet *
45
- frt_get_fields(VALUE rfields)
47
+ frb_get_fields(VALUE rfields)
46
48
  {
47
49
  VALUE rval;
48
50
  HashSet *fields;
@@ -50,12 +52,12 @@ frt_get_fields(VALUE rfields)
50
52
 
51
53
  if (rfields == Qnil) return NULL;
52
54
 
53
- fields = hs_new_str(&free);
55
+ fields = hs_new_ptr(NULL);
54
56
  if (TYPE(rfields) == T_ARRAY) {
55
57
  int i;
56
- for (i = 0; i < RARRAY(rfields)->len; i++) {
57
- rval = rb_obj_as_string(RARRAY(rfields)->ptr[i]);
58
- hs_add(fields, nstrdup(rval));
58
+ for (i = 0; i < RARRAY_LEN(rfields); i++) {
59
+ rval = rb_obj_as_string(RARRAY_PTR(rfields)[i]);
60
+ hs_add(fields, (char *)rintern(rval));
59
61
  }
60
62
  } else {
61
63
  rval = rb_obj_as_string(rfields);
@@ -63,19 +65,28 @@ frt_get_fields(VALUE rfields)
63
65
  hs_destroy(fields);
64
66
  fields = NULL;
65
67
  } else {
66
- s = str = nstrdup(rval);
68
+ s = str = rstrdup(rval);
67
69
  while ((p = strchr(s, '|')) != '\0') {
68
70
  *p = '\0';
69
- hs_add(fields, estrdup(s));
71
+ hs_add(fields, (char *)intern(s));
70
72
  s = p + 1;
71
73
  }
72
- hs_add(fields, estrdup(s));
74
+ hs_add(fields, (char *)intern(s));
73
75
  free(str);
74
76
  }
75
77
  }
76
78
  return fields;
77
79
  }
78
80
 
81
+ static void
82
+ hs_safe_merge(HashSet *merger, HashSet *mergee)
83
+ {
84
+ HashSetEntry *hse;
85
+ for (hse = mergee->first; hse; hse = hse->next) {
86
+ hs_add(merger, (char *)hse->elem);
87
+ }
88
+ }
89
+
79
90
  /*
80
91
  * call-seq:
81
92
  * QueryParser.new(options = {}) -> QueryParser
@@ -85,50 +96,60 @@ frt_get_fields(VALUE rfields)
85
96
  *
86
97
  * === Options
87
98
  *
88
- * :default_field:: Default: "*" (all fields). The default field to
89
- * search when no field is specified in the search
90
- * string. It can also be an array of fields.
91
- * :analyzer:: Default: StandardAnalyzer. Analyzer used by the
92
- * query parser to parse query terms
93
- * :wild_card_downcase:: Default: true. Specifies whether wild-card queries
94
- * and range queries should be downcased or not since
95
- * they are not passed through the parser
96
- * :fields:: Default: []. Lets the query parser know what
97
- * fields are available for searching, particularly
98
- * when the "*" is specified as the search field
99
- * :tokenized_fields:: Default: :fields. Lets the query parser know which
100
- * fields are tokenized so it knows which fields to
101
- * run the analyzer over.
102
- * :validate_fields:: Default: false. Set to true if you want an
103
- * exception to be raised if there is an attempt to
104
- * search a non-existent field
105
- * :or_default:: Default: true. Use "OR" as the default boolean
106
- * operator
107
- * :default_slop:: Default: 0. Default slop to use in PhraseQuery
108
- * :handle_parse_errors:: Default: true. QueryParser will quietly handle all
109
- * parsing errors internally. If you'd like to handle
110
- * them yourself, set this parameter to false.
111
- * :clean_string:: Default: true. QueryParser will do a quick
112
- * once-over the query string make sure that quotes
113
- * and brackets match up and special characters are
114
- * escaped
115
- * :max_clauses:: Default: 512. the maximum number of clauses
116
- * allowed in boolean queries and the maximum number
117
- * of terms allowed in multi, prefix, wild-card or
118
- * fuzzy queries when those queries are generated by
119
- * rewriting other queries
120
- * :use_keywords: Default: true. By default AND, OR, NOT and REQ are
121
- * keywords used by the query parser. Sometimes this
122
- * is undesirable. For example, if your application
123
- * allows searching for US states by their
124
- * abbreviation, then OR will be a common query
125
- * string. By setting :use_keywords to false, OR will
126
- * no longer be a keyword allowing searches for the
127
- * state of Oregon. You will still be able to use
128
- * boolean queries by using the + and - characters.
99
+ * :default_field:: Default: "*" (all fields). The default field to
100
+ * search when no field is specified in the search
101
+ * string. It can also be an array of fields.
102
+ * :analyzer:: Default: StandardAnalyzer. Analyzer used by the
103
+ * query parser to parse query terms
104
+ * :wild_card_downcase:: Default: true. Specifies whether wild-card queries
105
+ * and range queries should be downcased or not since
106
+ * they are not passed through the parser
107
+ * :fields:: Default: []. Lets the query parser know what
108
+ * fields are available for searching, particularly
109
+ * when the "*" is specified as the search field
110
+ * :tokenized_fields:: Default: :fields. Lets the query parser know which
111
+ * fields are tokenized so it knows which fields to
112
+ * run the analyzer over.
113
+ * :validate_fields:: Default: false. Set to true if you want an
114
+ * exception to be raised if there is an attempt to
115
+ * search a non-existent field
116
+ * :or_default:: Default: true. Use "OR" as the default boolean
117
+ * operator
118
+ * :default_slop:: Default: 0. Default slop to use in PhraseQuery
119
+ * :handle_parse_errors:: Default: true. QueryParser will quietly handle all
120
+ * parsing errors internally. If you'd like to handle
121
+ * them yourself, set this parameter to false.
122
+ * :clean_string:: Default: true. QueryParser will do a quick
123
+ * once-over the query string make sure that quotes
124
+ * and brackets match up and special characters are
125
+ * escaped
126
+ * :max_clauses:: Default: 512. the maximum number of clauses
127
+ * allowed in boolean queries and the maximum number
128
+ * of terms allowed in multi, prefix, wild-card or
129
+ * fuzzy queries when those queries are generated by
130
+ * rewriting other queries
131
+ * :use_keywords:: Default: true. By default AND, OR, NOT and REQ are
132
+ * keywords used by the query parser. Sometimes this
133
+ * is undesirable. For example, if your application
134
+ * allows searching for US states by their
135
+ * abbreviation, then OR will be a common query
136
+ * string. By setting :use_keywords to false, OR will
137
+ * no longer be a keyword allowing searches for the
138
+ * state of Oregon. You will still be able to use
139
+ * boolean queries by using the + and - characters.
140
+ * :use_typed_range_query:: Default: false. Use TypedRangeQuery instead of
141
+ * the standard RangeQuery when parsing
142
+ * range queries. This is useful if you have number
143
+ * fields which you want to perform range queries
144
+ * on. You won't need to pad or normalize the data
145
+ * in the field in anyway to get correct results.
146
+ * However, performance will be a lot slower for
147
+ * large indexes, hence the default.
148
+ * Note: the default is set to true in the Index
149
+ * class.
129
150
  */
130
151
  static VALUE
131
- frt_qp_init(int argc, VALUE *argv, VALUE self)
152
+ frb_qp_init(int argc, VALUE *argv, VALUE self)
132
153
  {
133
154
  VALUE roptions = Qnil;
134
155
  VALUE rval;
@@ -144,34 +165,45 @@ frt_qp_init(int argc, VALUE *argv, VALUE self)
144
165
  if (TYPE(roptions) == T_HASH) {
145
166
  has_options = true;
146
167
  if (Qnil != (rval = rb_hash_aref(roptions, sym_default_field))) {
147
- def_fields = frt_get_fields(rval);
168
+ def_fields = frb_get_fields(rval);
148
169
  }
149
170
  if (Qnil != (rval = rb_hash_aref(roptions, sym_analyzer))) {
150
- analyzer = frt_get_cwrapped_analyzer(rval);
171
+ analyzer = frb_get_cwrapped_analyzer(rval);
151
172
  }
152
173
  if (Qnil != (rval = rb_hash_aref(roptions, sym_all_fields))) {
153
- all_fields = frt_get_fields(rval);
174
+ all_fields = frb_get_fields(rval);
154
175
  }
155
176
  if (Qnil != (rval = rb_hash_aref(roptions, sym_fields))) {
156
- all_fields = frt_get_fields(rval);
177
+ all_fields = frb_get_fields(rval);
157
178
  }
158
179
  if (Qnil != (rval = rb_hash_aref(roptions, sym_tkz_fields))) {
159
- tkz_fields = frt_get_fields(rval);
180
+ tkz_fields = frb_get_fields(rval);
160
181
  }
161
182
  } else {
162
- def_fields = frt_get_fields(roptions);
183
+ def_fields = frb_get_fields(roptions);
163
184
  roptions = Qnil;
164
185
  }
165
186
  }
166
187
  if (all_fields == NULL) {
167
- all_fields = hs_new_str(&free);
188
+ all_fields = hs_new_ptr(NULL);
168
189
  }
169
190
 
170
191
  if (!analyzer) {
171
192
  analyzer = mb_standard_analyzer_new(true);
172
193
  }
173
194
 
174
- qp = qp_new(all_fields, def_fields, tkz_fields, analyzer);
195
+ qp = qp_new(analyzer);
196
+ hs_destroy(qp->all_fields);
197
+ hs_destroy(qp->def_fields);
198
+ //hs_destroy(qp->tokenized_fields);
199
+
200
+ if (def_fields) hs_safe_merge(all_fields, def_fields);
201
+ if (tkz_fields) hs_safe_merge(all_fields, tkz_fields);
202
+ qp->all_fields = all_fields;
203
+ qp->def_fields = def_fields ? def_fields : all_fields;
204
+ qp->tokenized_fields = tkz_fields ? tkz_fields : all_fields;
205
+ qp->fields_top->fields = def_fields;
206
+
175
207
  qp->allow_any_fields = true;
176
208
  qp->clean_str = true;
177
209
  qp->handle_parse_errors = true;
@@ -201,8 +233,11 @@ frt_qp_init(int argc, VALUE *argv, VALUE self)
201
233
  if (Qnil != (rval = rb_hash_aref(roptions, sym_use_keywords))) {
202
234
  qp->use_keywords = RTEST(rval);
203
235
  }
236
+ if (Qnil != (rval = rb_hash_aref(roptions, sym_use_typed_range_query))){
237
+ qp->use_typed_range_query = RTEST(rval);
238
+ }
204
239
  }
205
- Frt_Wrap_Struct(self, frt_qp_mark, frt_qp_free, qp);
240
+ Frt_Wrap_Struct(self, frb_qp_mark, frb_qp_free, qp);
206
241
  object_add(qp, self);
207
242
  return self;
208
243
  }
@@ -216,14 +251,14 @@ frt_qp_init(int argc, VALUE *argv, VALUE self)
216
251
  * Will raise a QueryParseException if unsuccessful.
217
252
  */
218
253
  static VALUE
219
- frt_qp_parse(VALUE self, VALUE rstr)
254
+ frb_qp_parse(VALUE self, VALUE rstr)
220
255
  {
221
256
  const char *msg = NULL;
222
257
  volatile VALUE rq;
223
258
  GET_QP;
224
259
  rstr = rb_obj_as_string(rstr);
225
260
  TRY
226
- rq = frt_get_q(qp_parse(qp, rs2s(rstr)));
261
+ rq = frb_get_q(qp_parse(qp, rs2s(rstr)));
227
262
  break;
228
263
  default:
229
264
  msg = xcontext.msg;
@@ -231,7 +266,7 @@ frt_qp_parse(VALUE self, VALUE rstr)
231
266
  XENDTRY
232
267
 
233
268
  if (msg) {
234
- rb_raise(cQueryParseException, msg);
269
+ rb_raise(cQueryParseException, "%s", msg);
235
270
  }
236
271
 
237
272
  return rq;
@@ -244,15 +279,15 @@ frt_qp_parse(VALUE self, VALUE rstr)
244
279
  * Returns the list of all fields that the QueryParser knows about.
245
280
  */
246
281
  static VALUE
247
- frt_qp_get_fields(VALUE self)
282
+ frb_qp_get_fields(VALUE self)
248
283
  {
249
284
  GET_QP;
250
- int i;
251
285
  HashSet *fields = qp->all_fields;
286
+ HashSetEntry *hse;
252
287
  VALUE rfields = rb_ary_new();
253
288
 
254
- for (i = 0; i < fields->size; i++) {
255
- rb_ary_push(rfields, ID2SYM(rb_intern((char *)fields->elems[i])));
289
+ for (hse = fields->first; hse; hse = hse->next) {
290
+ rb_ary_push(rfields, ID2SYM(rb_intern((char *)hse->elem)));
256
291
  }
257
292
 
258
293
  return rfields;
@@ -265,22 +300,34 @@ frt_qp_get_fields(VALUE self)
265
300
  * Set the list of fields. These fields are expanded for searches on "*".
266
301
  */
267
302
  static VALUE
268
- frt_qp_set_fields(VALUE self, VALUE rfields)
303
+ frb_qp_set_fields(VALUE self, VALUE rfields)
269
304
  {
270
305
  GET_QP;
271
- HashSet *fields = frt_get_fields(rfields);
306
+ HashSet *fields = frb_get_fields(rfields);
307
+
308
+ /* if def_fields == all_fields then we need to replace both */
309
+ if (qp->def_fields == qp->all_fields) qp->def_fields = NULL;
310
+ if (qp->tokenized_fields == qp->all_fields) qp->tokenized_fields = NULL;
272
311
 
273
- if (qp->def_fields == qp->all_fields) {
274
- qp->def_fields = NULL;
275
- }
276
312
  if (fields == NULL) {
277
- fields = hs_new_str(&free);
313
+ fields = hs_new_ptr(NULL);
278
314
  }
315
+
316
+ /* make sure all the fields in tokenized fields are contained in
317
+ * all_fields */
318
+ if (qp->tokenized_fields) hs_safe_merge(fields, qp->tokenized_fields);
319
+
320
+ /* delete old fields set */
321
+ assert(qp->all_fields->free_elem_i == dummy_free);
279
322
  hs_destroy(qp->all_fields);
323
+
324
+ /* add the new fields set and add to def_fields if necessary */
280
325
  qp->all_fields = fields;
281
326
  if (qp->def_fields == NULL) {
282
327
  qp->def_fields = fields;
328
+ qp->fields_top->fields = fields;
283
329
  }
330
+ if (qp->tokenized_fields == NULL) qp->tokenized_fields = fields;
284
331
 
285
332
  return self;
286
333
  }
@@ -292,16 +339,16 @@ frt_qp_set_fields(VALUE self, VALUE rfields)
292
339
  * Returns the list of all tokenized_fields that the QueryParser knows about.
293
340
  */
294
341
  static VALUE
295
- frt_qp_get_tkz_fields(VALUE self)
342
+ frb_qp_get_tkz_fields(VALUE self)
296
343
  {
297
344
  GET_QP;
298
- int i;
299
345
  HashSet *fields = qp->tokenized_fields;
300
346
  if (fields) {
301
347
  VALUE rfields = rb_ary_new();
348
+ HashSetEntry *hse;
302
349
 
303
- for (i = 0; i < fields->size; i++) {
304
- rb_ary_push(rfields, ID2SYM(rb_intern((char *)fields->elems[i])));
350
+ for (hse = fields->first; hse; hse = hse->next) {
351
+ rb_ary_push(rfields, ID2SYM(rb_intern((char *)hse->elem)));
305
352
  }
306
353
 
307
354
  return rfields;
@@ -319,11 +366,13 @@ frt_qp_get_tkz_fields(VALUE self)
319
366
  * the queries. If this is set to Qnil then all fields will be tokenized.
320
367
  */
321
368
  static VALUE
322
- frt_qp_set_tkz_fields(VALUE self, VALUE rfields)
369
+ frb_qp_set_tkz_fields(VALUE self, VALUE rfields)
323
370
  {
324
371
  GET_QP;
325
- if (qp->tokenized_fields) hs_destroy(qp->tokenized_fields);
326
- qp->tokenized_fields = frt_get_fields(rfields);
372
+ if (qp->tokenized_fields != qp->all_fields) {
373
+ hs_destroy(qp->tokenized_fields);
374
+ }
375
+ qp->tokenized_fields = frb_get_fields(rfields);
327
376
  return self;
328
377
  }
329
378
 
@@ -566,19 +615,20 @@ Init_QueryParser(void)
566
615
  sym_clean_string = ID2SYM(rb_intern("clean_string"));
567
616
  sym_max_clauses = ID2SYM(rb_intern("max_clauses"));
568
617
  sym_use_keywords = ID2SYM(rb_intern("use_keywords"));
618
+ sym_use_typed_range_query = ID2SYM(rb_intern("use_typed_range_query"));
569
619
 
570
620
  /* QueryParser */
571
621
  cQueryParser = rb_define_class_under(mFerret, "QueryParser", rb_cObject);
572
- rb_define_alloc_func(cQueryParser, frt_data_alloc);
622
+ rb_define_alloc_func(cQueryParser, frb_data_alloc);
573
623
 
574
- rb_define_method(cQueryParser, "initialize", frt_qp_init, -1);
575
- rb_define_method(cQueryParser, "parse", frt_qp_parse, 1);
576
- rb_define_method(cQueryParser, "fields", frt_qp_get_fields, 0);
577
- rb_define_method(cQueryParser, "fields=", frt_qp_set_fields, 1);
624
+ rb_define_method(cQueryParser, "initialize", frb_qp_init, -1);
625
+ rb_define_method(cQueryParser, "parse", frb_qp_parse, 1);
626
+ rb_define_method(cQueryParser, "fields", frb_qp_get_fields, 0);
627
+ rb_define_method(cQueryParser, "fields=", frb_qp_set_fields, 1);
578
628
  rb_define_method(cQueryParser, "tokenized_fields",
579
- frt_qp_get_tkz_fields, 0);
629
+ frb_qp_get_tkz_fields, 0);
580
630
  rb_define_method(cQueryParser, "tokenized_fields=",
581
- frt_qp_set_tkz_fields, 1);
631
+ frb_qp_set_tkz_fields, 1);
582
632
 
583
633
  Init_QueryParseException();
584
634
  }
@@ -1,6 +1,10 @@
1
1
  #include "ferret.h"
2
- #include <st.h>
3
- #include <rubysig.h>
2
+ #ifdef FRT_RUBY_VERSION_1_9
3
+ # include <ruby/st.h>
4
+ #else
5
+ # include <st.h>
6
+ # include <rubysig.h>
7
+ #endif
4
8
  #include <ctype.h>
5
9
  #include <array.h>
6
10
  #include "search.h"
@@ -22,6 +26,7 @@ static VALUE cMultiTermQuery;
22
26
  static VALUE cBooleanQuery;
23
27
  static VALUE cBooleanClause;
24
28
  static VALUE cRangeQuery;
29
+ static VALUE cTypedRangeQuery;
25
30
  static VALUE cPhraseQuery;
26
31
  static VALUE cPrefixQuery;
27
32
  static VALUE cWildcardQuery;
@@ -41,6 +46,7 @@ static VALUE cSpanNotQuery;
41
46
  static ID id_bits;
42
47
  static VALUE cFilter;
43
48
  static VALUE cRangeFilter;
49
+ static VALUE cTypedRangeFilter;
44
50
  static VALUE cQueryFilter;
45
51
 
46
52
  /* MultiTermQuery */
@@ -111,10 +117,12 @@ static ID id_searcher;
111
117
  /* Search */
112
118
  static VALUE sym_offset;
113
119
  static VALUE sym_limit;
120
+ static VALUE sym_start_doc;
114
121
  static VALUE sym_all;
115
122
  static VALUE sym_sort;
116
123
  static VALUE sym_filter;
117
124
  static VALUE sym_filter_proc;
125
+ static VALUE sym_c_filter_proc;
118
126
 
119
127
  static VALUE sym_excerpt_length;
120
128
  static VALUE sym_num_excerpts;
@@ -122,15 +130,17 @@ static VALUE sym_pre_tag;
122
130
  static VALUE sym_post_tag;
123
131
  static VALUE sym_ellipsis;
124
132
 
133
+ static Symbol fsym_id;
134
+
125
135
  extern VALUE cIndexReader;
126
- extern void frt_ir_free(void *p);
127
- extern void frt_ir_mark(void *p);
136
+ extern void frb_ir_free(void *p);
137
+ extern void frb_ir_mark(void *p);
128
138
 
129
- extern void frt_set_term(VALUE rterm, Term *t);
130
- extern VALUE frt_get_analyzer(Analyzer *a);
131
- extern HashSet *frt_get_fields(VALUE rfields);
132
- extern Analyzer *frt_get_cwrapped_analyzer(VALUE ranalyzer);
133
- extern VALUE frt_get_lazy_doc(LazyDoc *lazy_doc);
139
+ extern void frb_set_term(VALUE rterm, Term *t);
140
+ extern VALUE frb_get_analyzer(Analyzer *a);
141
+ extern HashSet *frb_get_fields(VALUE rfields);
142
+ extern Analyzer *frb_get_cwrapped_analyzer(VALUE ranalyzer);
143
+ extern VALUE frb_get_lazy_doc(LazyDoc *lazy_doc);
134
144
 
135
145
  /****************************************************************************
136
146
  *
@@ -139,7 +149,7 @@ extern VALUE frt_get_lazy_doc(LazyDoc *lazy_doc);
139
149
  ****************************************************************************/
140
150
 
141
151
  static VALUE
142
- frt_get_hit(Hit *hit)
152
+ frb_get_hit(Hit *hit)
143
153
  {
144
154
  return rb_struct_new(cHit,
145
155
  INT2FIX(hit->doc),
@@ -154,15 +164,14 @@ frt_get_hit(Hit *hit)
154
164
  ****************************************************************************/
155
165
 
156
166
  static VALUE
157
- frt_get_td(TopDocs *td, VALUE rsearcher)
167
+ frb_get_td(TopDocs *td, VALUE rsearcher)
158
168
  {
159
169
  int i;
160
170
  VALUE rtop_docs;
161
171
  VALUE hit_ary = rb_ary_new2(td->size);
162
172
 
163
173
  for (i = 0; i < td->size; i++) {
164
- RARRAY(hit_ary)->ptr[i] = frt_get_hit(td->hits[i]);
165
- RARRAY(hit_ary)->len++;
174
+ rb_ary_store(hit_ary, i, frb_get_hit(td->hits[i]));
166
175
  }
167
176
 
168
177
  rtop_docs = rb_struct_new(cTopDocs,
@@ -182,50 +191,57 @@ frt_get_td(TopDocs *td, VALUE rsearcher)
182
191
  * Returns a string representation of the top_doc in readable format.
183
192
  */
184
193
  static VALUE
185
- frt_td_to_s(int argc, VALUE *argv, VALUE self)
194
+ frb_td_to_s(int argc, VALUE *argv, VALUE self)
186
195
  {
187
196
  int i;
188
197
  VALUE rhits = rb_funcall(self, id_hits, 0);
189
198
  Searcher *sea = (Searcher *)DATA_PTR(rb_funcall(self, id_searcher, 0));
190
- const int len = RARRAY(rhits)->len;
199
+ const int len = RARRAY_LEN(rhits);
200
+ int capa = len * 64 + 100;
201
+ int p = 0;
191
202
  char *str = ALLOC_N(char, len * 64 + 100);
192
- char *s = str;
193
- char *field = "id";
203
+ Symbol field = fsym_id;
194
204
  VALUE rstr;
195
205
 
196
206
  if (argc) {
197
- field = frt_field(argv[0]);
207
+ field = frb_field(argv[0]);
198
208
  }
199
209
 
200
- sprintf(s, "TopDocs: total_hits = %ld, max_score = %f [\n",
201
- FIX2INT(rb_funcall(self, id_total_hits, 0)),
210
+ sprintf(str, "TopDocs: total_hits = %ld, max_score = %lf [\n",
211
+ FIX2LONG(rb_funcall(self, id_total_hits, 0)),
202
212
  NUM2DBL(rb_funcall(self, id_max_score, 0)));
203
- s += strlen(s);
213
+ p = (int)strlen(str);
204
214
 
205
215
  for (i = 0; i < len; i++) {
206
- VALUE rhit = RARRAY(rhits)->ptr[i];
216
+ VALUE rhit = RARRAY_PTR(rhits)[i];
207
217
  int doc_id = FIX2INT(rb_funcall(rhit, id_doc, 0));
208
218
  char *value = "";
219
+ size_t value_len = 0;
209
220
  LazyDoc *lzd = sea->get_lazy_doc(sea, doc_id);
210
- LazyDocField *lzdf = h_get(lzd->field_dict, field);
221
+ LazyDocField *lzdf = lazy_doc_get(lzd, field);
211
222
  if (NULL != lzdf) {
212
223
  value = lazy_df_get_data(lzdf, 0);
224
+ value_len = strlen(value);
225
+ }
226
+ if (p + value_len + 64 > capa) {
227
+ capa += (value_len + 64) * (len - i);
228
+ REALLOC_N(str, char, capa);
213
229
  }
214
230
 
215
- sprintf(s, "\t%d \"%s\": %f\n", doc_id, value,
231
+ sprintf(str + p, "\t%d \"%s\": %0.5f\n", doc_id, value,
216
232
  NUM2DBL(rb_funcall(rhit, id_score, 0)));
217
- s += strlen(s);
233
+ p += strlen(str + p);
218
234
  lazy_doc_close(lzd);
219
235
  }
220
236
 
221
- sprintf(s, "]\n");
237
+ sprintf(str + p, "]\n");
222
238
  rstr = rb_str_new2(str);
223
239
  free(str);
224
240
  return rstr;
225
241
  }
226
242
 
227
243
  static INLINE char *
228
- frt_lzd_load_to_json(LazyDoc *lzd, char **str, char *s, int *slen)
244
+ frb_lzd_load_to_json(LazyDoc *lzd, char **str, char *s, int *slen)
229
245
  {
230
246
  int i, j;
231
247
  int diff = s - *str;
@@ -238,7 +254,7 @@ frt_lzd_load_to_json(LazyDoc *lzd, char **str, char *s, int *slen)
238
254
  * 4 times field elements to make space for '"' around fields and ','
239
255
  * between fields. Add 100 for '[', ']' and good safety.
240
256
  */
241
- len += strlen(f->name) + f->len * 3 + 100 + 4 * f->size;
257
+ len += sym_len(f->name) + f->len * 3 + 100 + 4 * f->size;
242
258
  }
243
259
 
244
260
  if (len > *slen) {
@@ -248,11 +264,13 @@ frt_lzd_load_to_json(LazyDoc *lzd, char **str, char *s, int *slen)
248
264
  }
249
265
 
250
266
  for (i = 0; i < lzd->size; i++) {
267
+ const char *field_name;
251
268
  f = lzd->fields[i];
269
+ field_name = S(f->name);
252
270
  if (i) *(s++) = ',';
253
271
  *(s++) = '"';
254
- l = strlen(f->name);
255
- memcpy(s, f->name, l);
272
+ l = strlen(field_name);
273
+ memcpy(s, field_name, l);
256
274
  s += l;
257
275
  *(s++) = '"';
258
276
  *(s++) = ':';
@@ -273,14 +291,14 @@ frt_lzd_load_to_json(LazyDoc *lzd, char **str, char *s, int *slen)
273
291
  * Returns a json representation of the top_doc.
274
292
  */
275
293
  static VALUE
276
- frt_td_to_json(VALUE self)
294
+ frb_td_to_json(VALUE self)
277
295
  {
278
296
  int i;
279
297
  VALUE rhits = rb_funcall(self, id_hits, 0);
280
298
  VALUE rhit;
281
299
  LazyDoc *lzd;
282
300
  Searcher *sea = (Searcher *)DATA_PTR(rb_funcall(self, id_searcher, 0));
283
- const int num_hits = RARRAY(rhits)->len;
301
+ const int num_hits = RARRAY_LEN(rhits);
284
302
  int doc_id;
285
303
  int len = 32768;
286
304
  char *str = ALLOC_N(char, len);
@@ -291,10 +309,10 @@ frt_td_to_json(VALUE self)
291
309
  for (i = 0; i < num_hits; i++) {
292
310
  if (i) *(s++) = ',';
293
311
  *(s++) = '{';
294
- rhit = RARRAY(rhits)->ptr[i];
312
+ rhit = RARRAY_PTR(rhits)[i];
295
313
  doc_id = FIX2INT(rb_funcall(rhit, id_doc, 0));
296
314
  lzd = sea->get_lazy_doc(sea, doc_id);
297
- s = frt_lzd_load_to_json(lzd, &str, s, &len);
315
+ s = frb_lzd_load_to_json(lzd, &str, s, &len);
298
316
  lazy_doc_close(lzd);
299
317
  *(s++) = '}';
300
318
  }
@@ -321,7 +339,7 @@ frt_td_to_json(VALUE self)
321
339
  * Returns a string representation of the explanation in readable format.
322
340
  */
323
341
  static VALUE
324
- frt_expl_to_s(VALUE self)
342
+ frb_expl_to_s(VALUE self)
325
343
  {
326
344
  GET_EXPL();
327
345
  char *str = expl_to_s(expl);
@@ -337,7 +355,7 @@ frt_expl_to_s(VALUE self)
337
355
  * Returns an html representation of the explanation in readable format.
338
356
  */
339
357
  static VALUE
340
- frt_expl_to_html(VALUE self)
358
+ frb_expl_to_html(VALUE self)
341
359
  {
342
360
  GET_EXPL();
343
361
  char *str = expl_to_html(expl);
@@ -355,7 +373,7 @@ frt_expl_to_html(VALUE self)
355
373
  * matches that of the score for the document in the original query.
356
374
  */
357
375
  static VALUE
358
- frt_expl_score(VALUE self)
376
+ frb_expl_score(VALUE self)
359
377
  {
360
378
  GET_EXPL();
361
379
  return rb_float_new((double)expl->value);
@@ -368,7 +386,7 @@ frt_expl_score(VALUE self)
368
386
  ****************************************************************************/
369
387
 
370
388
  static void
371
- frt_q_free(void *p)
389
+ frb_q_free(void *p)
372
390
  {
373
391
  object_del(p);
374
392
  q_deref((Query *)p);
@@ -385,13 +403,14 @@ frt_q_free(void *p)
385
403
  * began with. This can be a good way to explore how the QueryParser works.
386
404
  */
387
405
  static VALUE
388
- frt_q_to_s(int argc, VALUE *argv, VALUE self)
406
+ frb_q_to_s(int argc, VALUE *argv, VALUE self)
389
407
  {
390
408
  GET_Q();
391
409
  VALUE rstr, rfield;
392
- char *str, *field = "";
410
+ char *str;
411
+ Symbol field = NULL;
393
412
  if (rb_scan_args(argc, argv, "01", &rfield)) {
394
- field = frt_field(rfield);
413
+ field = frb_field(rfield);
395
414
  }
396
415
  str = q->to_s(q, field);
397
416
  rstr = rb_str_new2(str);
@@ -407,7 +426,7 @@ frt_q_to_s(int argc, VALUE *argv, VALUE self)
407
426
  * information on Query boosts.
408
427
  */
409
428
  static VALUE
410
- frt_q_get_boost(VALUE self)
429
+ frb_q_get_boost(VALUE self)
411
430
  {
412
431
  GET_Q();
413
432
  return rb_float_new((double)q->boost);
@@ -421,7 +440,7 @@ frt_q_get_boost(VALUE self)
421
440
  * on Query boosts.
422
441
  */
423
442
  static VALUE
424
- frt_q_set_boost(VALUE self, VALUE rboost)
443
+ frb_q_set_boost(VALUE self, VALUE rboost)
425
444
  {
426
445
  GET_Q();
427
446
  q->boost = (float)NUM2DBL(rboost);
@@ -436,7 +455,7 @@ frt_q_set_boost(VALUE self, VALUE rboost)
436
455
  * in a hash object.
437
456
  */
438
457
  static VALUE
439
- frt_q_hash(VALUE self)
458
+ frb_q_hash(VALUE self)
440
459
  {
441
460
  GET_Q();
442
461
  return INT2FIX(q->hash(q));
@@ -456,7 +475,7 @@ frt_q_hash(VALUE self)
456
475
  * expected however.
457
476
  */
458
477
  static VALUE
459
- frt_q_eql(VALUE self, VALUE other)
478
+ frb_q_eql(VALUE self, VALUE other)
460
479
  {
461
480
  GET_Q();
462
481
  Query *oq;
@@ -474,27 +493,30 @@ frt_q_eql(VALUE self, VALUE other)
474
493
  * in a real search.
475
494
  */
476
495
  static VALUE
477
- frt_q_get_terms(VALUE self, VALUE searcher)
496
+ frb_q_get_terms(VALUE self, VALUE searcher)
478
497
  {
479
- int i;
480
498
  VALUE rterms = rb_ary_new();
481
- HashSet *terms = term_set_new();
499
+ HashSet *terms = hs_new((hash_ft)&term_hash,
500
+ (eq_ft)&term_eq,
501
+ (free_ft)term_destroy);
502
+ HashSetEntry *hse;
482
503
  GET_Q();
483
504
  Searcher *sea = (Searcher *)DATA_PTR(searcher);
484
505
  Query *rq = sea->rewrite(sea, q);
485
506
  rq->extract_terms(rq, terms);
486
507
  q_deref(rq);
487
- for (i = 0; i < terms->size; i++) {
488
- Term *term = (Term *)terms->elems[i];
489
- rb_ary_push(rterms, frt_get_term(term->field, term->text));
508
+
509
+ for (hse = terms->first; hse; hse = hse->next) {
510
+ Term *term = (Term *)hse->elem;
511
+ rb_ary_push(rterms, frb_get_term(term->field, term->text));
490
512
  }
491
513
  hs_destroy(terms);
492
514
  return rterms;
493
515
  }
494
516
 
495
- #define MK_QUERY(klass, q) Data_Wrap_Struct(klass, NULL, &frt_q_free, q)
517
+ #define MK_QUERY(klass, q) Data_Wrap_Struct(klass, NULL, &frb_q_free, q)
496
518
  VALUE
497
- frt_get_q(Query *q)
519
+ frb_get_q(Query *q)
498
520
  {
499
521
  VALUE self = object_get(q);
500
522
 
@@ -524,6 +546,9 @@ frt_get_q(Query *q)
524
546
  case RANGE_QUERY:
525
547
  self = MK_QUERY(cRangeQuery, q);
526
548
  break;
549
+ case TYPED_RANGE_QUERY:
550
+ self = MK_QUERY(cTypedRangeQuery, q);
551
+ break;
527
552
  case WILD_CARD_QUERY:
528
553
  self = MK_QUERY(cWildcardQuery, q);
529
554
  break;
@@ -579,12 +604,12 @@ frt_get_q(Query *q)
579
604
  * Note: As usual, field should be a symbol
580
605
  */
581
606
  static VALUE
582
- frt_tq_init(VALUE self, VALUE rfield, VALUE rterm)
607
+ frb_tq_init(VALUE self, VALUE rfield, VALUE rterm)
583
608
  {
584
- char *field = frt_field(rfield);
609
+ Symbol field = frb_field(rfield);
585
610
  char *term = rs2s(rb_obj_as_string(rterm));
586
611
  Query *q = tq_new(field, term);
587
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
612
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
588
613
  object_add(q, self);
589
614
  return self;
590
615
  }
@@ -603,7 +628,7 @@ frt_tq_init(VALUE self, VALUE rfield, VALUE rterm)
603
628
  * also used by PrefixQuery, FuzzyQuery and WildcardQuery.
604
629
  */
605
630
  static VALUE
606
- frt_mtq_get_dmt(VALUE self)
631
+ frb_mtq_get_dmt(VALUE self)
607
632
  {
608
633
  return rb_cvar_get(cMultiTermQuery, id_default_max_terms);
609
634
  }
@@ -616,14 +641,18 @@ frt_mtq_get_dmt(VALUE self)
616
641
  * also used by PrefixQuery, FuzzyQuery and WildcardQuery.
617
642
  */
618
643
  static VALUE
619
- frt_mtq_set_dmt(VALUE self, VALUE rnum_terms)
644
+ frb_mtq_set_dmt(VALUE self, VALUE rnum_terms)
620
645
  {
621
646
  int max_terms = FIX2INT(rnum_terms);
622
647
  if (max_terms <= 0) {
623
648
  rb_raise(rb_eArgError,
624
649
  "%d <= 0. @@max_terms must be > 0", max_terms);
625
650
  }
651
+ #ifdef FRT_RUBY_VERSION_1_9
652
+ rb_cvar_set(cMultiTermQuery, id_default_max_terms, rnum_terms);
653
+ #else
626
654
  rb_cvar_set(cMultiTermQuery, id_default_max_terms, rnum_terms, Qfalse);
655
+ #endif
627
656
  return rnum_terms;
628
657
  }
629
658
 
@@ -652,11 +681,11 @@ frt_mtq_set_dmt(VALUE self, VALUE rnum_terms)
652
681
  * FuzzyQuery in particular makes use of this parameter.
653
682
  */
654
683
  static VALUE
655
- frt_mtq_init(int argc, VALUE *argv, VALUE self)
684
+ frb_mtq_init(int argc, VALUE *argv, VALUE self)
656
685
  {
657
686
  VALUE rfield, roptions;
658
687
  float min_score = 0.0;
659
- int max_terms = FIX2INT(frt_mtq_get_dmt(self));
688
+ int max_terms = FIX2INT(frb_mtq_get_dmt(self));
660
689
  Query *q;
661
690
 
662
691
  if (rb_scan_args(argc, argv, "11", &rfield, &roptions) == 2) {
@@ -668,8 +697,8 @@ frt_mtq_init(int argc, VALUE *argv, VALUE self)
668
697
  min_score = (float)NUM2DBL(v);
669
698
  }
670
699
  }
671
- q = multi_tq_new_conf(frt_field(rfield), max_terms, min_score);
672
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
700
+ q = multi_tq_new_conf(frb_field(rfield), max_terms, min_score);
701
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
673
702
  object_add(q, self);
674
703
  return self;
675
704
  }
@@ -683,7 +712,7 @@ frt_mtq_init(int argc, VALUE *argv, VALUE self)
683
712
  * otherwise.
684
713
  */
685
714
  static VALUE
686
- frt_mtq_add_term(int argc, VALUE *argv, VALUE self)
715
+ frb_mtq_add_term(int argc, VALUE *argv, VALUE self)
687
716
  {
688
717
  GET_Q();
689
718
  VALUE rterm, rboost;
@@ -698,10 +727,29 @@ frt_mtq_add_term(int argc, VALUE *argv, VALUE self)
698
727
  return self;
699
728
  }
700
729
 
701
- typedef Query *(*mtq_maker_ft)(const char *field, const char *term);
730
+ typedef Query *(*mtq_maker_ft)(Symbol field, const char *term);
731
+
732
+ static int
733
+ get_max_terms(VALUE rmax_terms, int max_terms)
734
+ {
735
+ VALUE v;
736
+ switch (TYPE(rmax_terms)) {
737
+ case T_HASH:
738
+ if (Qnil != (v = rb_hash_aref(rmax_terms, sym_max_terms))) {
739
+ max_terms = FIX2INT(v);
740
+ }
741
+ break;
742
+ case T_FIXNUM:
743
+ max_terms = FIX2INT(rmax_terms);
744
+ break;
745
+ default:
746
+ rb_raise(rb_eArgError, "max_terms must be an integer");
747
+ }
748
+ return max_terms;
749
+ }
702
750
 
703
751
  static VALUE
704
- frt_mtq_init_specific(int argc, VALUE *argv, VALUE self, mtq_maker_ft mm)
752
+ frb_mtq_init_specific(int argc, VALUE *argv, VALUE self, mtq_maker_ft mm)
705
753
  {
706
754
  VALUE rfield, rterm, rmax_terms;
707
755
  int max_terms =
@@ -709,12 +757,12 @@ frt_mtq_init_specific(int argc, VALUE *argv, VALUE self, mtq_maker_ft mm)
709
757
  Query *q;
710
758
 
711
759
  if (rb_scan_args(argc, argv, "21", &rfield, &rterm, &rmax_terms) == 3) {
712
- max_terms = FIX2INT(rmax_terms);
760
+ max_terms = get_max_terms(rmax_terms, max_terms);
713
761
  }
714
762
 
715
- q = (*mm)(frt_field(rfield), StringValuePtr(rterm));
763
+ q = (*mm)(frb_field(rfield), StringValuePtr(rterm));
716
764
  MTQMaxTerms(q) = max_terms;
717
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
765
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
718
766
  object_add(q, self);
719
767
  return self;
720
768
  }
@@ -726,31 +774,31 @@ frt_mtq_init_specific(int argc, VALUE *argv, VALUE self, mtq_maker_ft mm)
726
774
  ****************************************************************************/
727
775
 
728
776
  static void
729
- frt_bc_mark(void *p)
777
+ frb_bc_mark(void *p)
730
778
  {
731
- frt_gc_mark(((BooleanClause *)p)->query);
779
+ frb_gc_mark(((BooleanClause *)p)->query);
732
780
  }
733
781
 
734
782
  static void
735
- frt_bc_free(void *p)
783
+ frb_bc_free(void *p)
736
784
  {
737
785
  object_del(p);
738
786
  bc_deref((BooleanClause *)p);
739
787
  }
740
788
 
741
789
  static VALUE
742
- frt_bc_wrap(BooleanClause *bc)
790
+ frb_bc_wrap(BooleanClause *bc)
743
791
  {
744
- VALUE self = Data_Wrap_Struct(cBooleanClause, &frt_bc_mark, &frt_bc_free, bc);
792
+ VALUE self = Data_Wrap_Struct(cBooleanClause, &frb_bc_mark, &frb_bc_free, bc);
745
793
  REF(bc);
746
794
  object_add(bc, self);
747
795
  return self;
748
796
  }
749
797
 
750
- static enum BC_TYPE
751
- frt_get_occur(VALUE roccur)
798
+ static BCType
799
+ frb_get_occur(VALUE roccur)
752
800
  {
753
- enum BC_TYPE occur = BC_SHOULD;
801
+ BCType occur = BC_SHOULD;
754
802
 
755
803
  if (roccur == sym_should) {
756
804
  occur = BC_SHOULD;
@@ -773,19 +821,19 @@ frt_get_occur(VALUE roccur)
773
821
  * must be one of +:must+, +:should+ or +:must_not+.
774
822
  */
775
823
  static VALUE
776
- frt_bc_init(int argc, VALUE *argv, VALUE self)
824
+ frb_bc_init(int argc, VALUE *argv, VALUE self)
777
825
  {
778
826
  BooleanClause *bc;
779
827
  VALUE rquery, roccur;
780
828
  unsigned int occur = BC_SHOULD;
781
829
  Query *sub_q;
782
830
  if (rb_scan_args(argc, argv, "11", &rquery, &roccur) == 2) {
783
- occur = frt_get_occur(roccur);
831
+ occur = frb_get_occur(roccur);
784
832
  }
785
833
  Data_Get_Struct(rquery, Query, sub_q);
786
834
  REF(sub_q);
787
835
  bc = bc_new(sub_q, occur);
788
- Frt_Wrap_Struct(self, &frt_bc_mark, &frt_bc_free, bc);
836
+ Frt_Wrap_Struct(self, &frb_bc_mark, &frb_bc_free, bc);
789
837
  object_add(bc, self);
790
838
  return self;
791
839
  }
@@ -798,7 +846,7 @@ frt_bc_init(int argc, VALUE *argv, VALUE self)
798
846
  * Return the query object wrapped by this BooleanClause.
799
847
  */
800
848
  static VALUE
801
- frt_bc_get_query(VALUE self)
849
+ frb_bc_get_query(VALUE self)
802
850
  {
803
851
  GET_BC();
804
852
  return object_get(bc->query);
@@ -811,7 +859,7 @@ frt_bc_get_query(VALUE self)
811
859
  * Set the query wrapped by this BooleanClause.
812
860
  */
813
861
  static VALUE
814
- frt_bc_set_query(VALUE self, VALUE rquery)
862
+ frb_bc_set_query(VALUE self, VALUE rquery)
815
863
  {
816
864
  GET_BC();
817
865
  Data_Get_Struct(rquery, Query, bc->query);
@@ -826,7 +874,7 @@ frt_bc_set_query(VALUE self, VALUE rquery)
826
874
  * equal to +:must+.
827
875
  */
828
876
  static VALUE
829
- frt_bc_is_required(VALUE self)
877
+ frb_bc_is_required(VALUE self)
830
878
  {
831
879
  GET_BC();
832
880
  return bc->is_required ? Qtrue : Qfalse;
@@ -840,7 +888,7 @@ frt_bc_is_required(VALUE self)
840
888
  * equal to +:must_not+.
841
889
  */
842
890
  static VALUE
843
- frt_bc_is_prohibited(VALUE self)
891
+ frb_bc_is_prohibited(VALUE self)
844
892
  {
845
893
  GET_BC();
846
894
  return bc->is_prohibited ? Qtrue : Qfalse;
@@ -854,10 +902,10 @@ frt_bc_is_prohibited(VALUE self)
854
902
  * +:must+, +:should+ or +:must_not+.
855
903
  */
856
904
  static VALUE
857
- frt_bc_set_occur(VALUE self, VALUE roccur)
905
+ frb_bc_set_occur(VALUE self, VALUE roccur)
858
906
  {
859
907
  GET_BC();
860
- enum BC_TYPE occur = frt_get_occur(roccur);
908
+ BCType occur = frb_get_occur(roccur);
861
909
  bc_set_occur(bc, occur);
862
910
 
863
911
  return roccur;
@@ -872,13 +920,13 @@ frt_bc_set_occur(VALUE self, VALUE roccur)
872
920
  * whether the clause is +:must+, +:should+ or +:must_not+.
873
921
  */
874
922
  static VALUE
875
- frt_bc_to_s(VALUE self)
923
+ frb_bc_to_s(VALUE self)
876
924
  {
877
925
  VALUE rstr;
878
926
  char *qstr, *ostr = "", *str;
879
927
  int len;
880
928
  GET_BC();
881
- qstr = bc->query->to_s(bc->query, "");
929
+ qstr = bc->query->to_s(bc->query, NULL);
882
930
  switch (bc->occur) {
883
931
  case BC_SHOULD:
884
932
  ostr = "Should";
@@ -906,13 +954,13 @@ frt_bc_to_s(VALUE self)
906
954
  ****************************************************************************/
907
955
 
908
956
  static void
909
- frt_bq_mark(void *p)
957
+ frb_bq_mark(void *p)
910
958
  {
911
959
  int i;
912
960
  Query *q = (Query *)p;
913
961
  BooleanQuery *bq = (BooleanQuery *)q;
914
962
  for (i = 0; i < bq->clause_cnt; i++) {
915
- frt_gc_mark(bq->clauses[i]);
963
+ frb_gc_mark(bq->clauses[i]);
916
964
  }
917
965
  }
918
966
 
@@ -927,7 +975,7 @@ frt_bq_mark(void *p)
927
975
  * should leave this parameter as is.
928
976
  */
929
977
  static VALUE
930
- frt_bq_init(int argc, VALUE *argv, VALUE self)
978
+ frb_bq_init(int argc, VALUE *argv, VALUE self)
931
979
  {
932
980
  VALUE rcoord_disabled;
933
981
  bool coord_disabled = false;
@@ -936,7 +984,7 @@ frt_bq_init(int argc, VALUE *argv, VALUE self)
936
984
  coord_disabled = RTEST(rcoord_disabled);
937
985
  }
938
986
  q = bq_new(coord_disabled);
939
- Frt_Wrap_Struct(self, &frt_bq_mark, &frt_q_free, q);
987
+ Frt_Wrap_Struct(self, &frb_bq_mark, &frb_q_free, q);
940
988
  object_add(q, self);
941
989
  return self;
942
990
  }
@@ -963,16 +1011,16 @@ frt_bq_init(int argc, VALUE *argv, VALUE self)
963
1011
  * returns:: BooleanClause which was added
964
1012
  */
965
1013
  static VALUE
966
- frt_bq_add_query(int argc, VALUE *argv, VALUE self)
1014
+ frb_bq_add_query(int argc, VALUE *argv, VALUE self)
967
1015
  {
968
1016
  GET_Q();
969
1017
  VALUE rquery, roccur;
970
- enum BC_TYPE occur = BC_SHOULD;
1018
+ BCType occur = BC_SHOULD;
971
1019
  Query *sub_q;
972
1020
  VALUE klass;
973
1021
 
974
1022
  if (rb_scan_args(argc, argv, "11", &rquery, &roccur) == 2) {
975
- occur = frt_get_occur(roccur);
1023
+ occur = frb_get_occur(roccur);
976
1024
  }
977
1025
  klass = CLASS_OF(rquery);
978
1026
  if (klass == cBooleanClause) {
@@ -985,7 +1033,7 @@ frt_bq_add_query(int argc, VALUE *argv, VALUE self)
985
1033
  return rquery;
986
1034
  } else if (TYPE(rquery) == T_DATA) {
987
1035
  Data_Get_Struct(rquery, Query, sub_q);
988
- return frt_bc_wrap(bq_add_query(q, sub_q, occur));
1036
+ return frb_bc_wrap(bq_add_query(q, sub_q, occur));
989
1037
  } else {
990
1038
  rb_raise(rb_eArgError, "Cannot add %s to a BooleanQuery",
991
1039
  rb_class2name(klass));
@@ -1006,19 +1054,19 @@ get_range_params(VALUE roptions, char **lterm, char **uterm,
1006
1054
  VALUE v;
1007
1055
  Check_Type(roptions, T_HASH);
1008
1056
  if (Qnil != (v = rb_hash_aref(roptions, sym_lower))) {
1009
- *lterm = StringValuePtr(v);
1057
+ *lterm = rs2s(rb_obj_as_string(v));
1010
1058
  *include_lower = true;
1011
1059
  }
1012
1060
  if (Qnil != (v = rb_hash_aref(roptions, sym_upper))) {
1013
- *uterm = StringValuePtr(v);
1061
+ *uterm = rs2s(rb_obj_as_string(v));
1014
1062
  *include_upper = true;
1015
1063
  }
1016
1064
  if (Qnil != (v = rb_hash_aref(roptions, sym_lower_exclusive))) {
1017
- *lterm = StringValuePtr(v);
1065
+ *lterm = rs2s(rb_obj_as_string(v));
1018
1066
  *include_lower = false;
1019
1067
  }
1020
1068
  if (Qnil != (v = rb_hash_aref(roptions, sym_upper_exclusive))) {
1021
- *uterm = StringValuePtr(v);
1069
+ *uterm = rs2s(rb_obj_as_string(v));
1022
1070
  *include_upper = false;
1023
1071
  }
1024
1072
  if (Qnil != (v = rb_hash_aref(roptions, sym_include_lower))) {
@@ -1028,19 +1076,19 @@ get_range_params(VALUE roptions, char **lterm, char **uterm,
1028
1076
  *include_upper = RTEST(v);
1029
1077
  }
1030
1078
  if (Qnil != (v = rb_hash_aref(roptions, sym_greater_than))) {
1031
- *lterm = StringValuePtr(v);
1079
+ *lterm = rs2s(rb_obj_as_string(v));
1032
1080
  *include_lower = false;
1033
1081
  }
1034
1082
  if (Qnil != (v = rb_hash_aref(roptions, sym_greater_than_or_equal_to))) {
1035
- *lterm = StringValuePtr(v);
1083
+ *lterm = rs2s(rb_obj_as_string(v));
1036
1084
  *include_lower = true;
1037
1085
  }
1038
1086
  if (Qnil != (v = rb_hash_aref(roptions, sym_less_than))) {
1039
- *uterm = StringValuePtr(v);
1087
+ *uterm = rs2s(rb_obj_as_string(v));
1040
1088
  *include_upper = false;
1041
1089
  }
1042
1090
  if (Qnil != (v = rb_hash_aref(roptions, sym_less_than_or_equal_to))) {
1043
- *uterm = StringValuePtr(v);
1091
+ *uterm = rs2s(rb_obj_as_string(v));
1044
1092
  *include_upper = true;
1045
1093
  }
1046
1094
  if (!*lterm && !*uterm) {
@@ -1055,11 +1103,6 @@ get_range_params(VALUE roptions, char **lterm, char **uterm,
1055
1103
  rb_raise(rb_eArgError,
1056
1104
  "The upper bound should not be nil if it is inclusive");
1057
1105
  }
1058
- if (*uterm && *lterm && (strcmp(*uterm, *lterm) < 0)) {
1059
- rb_raise(rb_eArgError,
1060
- "The upper bound should greater than the lower bound."
1061
- " %s > %s", *lterm, *uterm);
1062
- }
1063
1106
  }
1064
1107
 
1065
1108
  /*
@@ -1083,9 +1126,10 @@ get_range_params(VALUE roptions, char **lterm, char **uterm,
1083
1126
  * q = RangeQuery.new(:date, :lower => "200501", :upper => 200502)
1084
1127
  * # is equivalent to
1085
1128
  * q = RangeQuery.new(:date, :>= => "200501", :<= => 200502)
1129
+ *
1086
1130
  */
1087
1131
  static VALUE
1088
- frt_rq_init(VALUE self, VALUE rfield, VALUE roptions)
1132
+ frb_rq_init(VALUE self, VALUE rfield, VALUE roptions)
1089
1133
  {
1090
1134
  Query *q;
1091
1135
  char *lterm = NULL;
@@ -1094,10 +1138,62 @@ frt_rq_init(VALUE self, VALUE rfield, VALUE roptions)
1094
1138
  bool include_upper = false;
1095
1139
 
1096
1140
  get_range_params(roptions, &lterm, &uterm, &include_lower, &include_upper);
1097
- q = rq_new(frt_field(rfield),
1141
+ q = rq_new(frb_field(rfield),
1098
1142
  lterm, uterm,
1099
1143
  include_lower, include_upper);
1100
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1144
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1145
+ object_add(q, self);
1146
+ return self;
1147
+ }
1148
+
1149
+ /****************************************************************************
1150
+ *
1151
+ * TypedRangeQuery Methods
1152
+ *
1153
+ ****************************************************************************/
1154
+
1155
+ /*
1156
+ * call-seq:
1157
+ * TypedRangeQuery.new(field, options = {}) -> range_query
1158
+ *
1159
+ * Create a new TypedRangeQuery on field +field+. This differs from the
1160
+ * standard RangeQuery in that it allows range queries with unpadded numbers,
1161
+ * both positive and negative, integer and float. You can even use
1162
+ * hexadecimal numbers. However it could be a lot slower than the standard
1163
+ * RangeQuery on large indexes.
1164
+ *
1165
+ * There are two ways to build a range query. With the old-style options;
1166
+ * +:lower+, +:upper+, +:include_lower+ and +:include_upper+ or the new style
1167
+ * options; +:<+, +:<=+, +:>+ and +:>=+. The options' names should speak for
1168
+ * themselves. In the old-style options, limits are inclusive by default.
1169
+ *
1170
+ * == Examples
1171
+ *
1172
+ * q = TypedRangeQuery.new(:date, :lower => "0.1", :include_lower => false)
1173
+ * # is equivalent to
1174
+ * q = TypedRangeQuery.new(:date, :< => "0.1")
1175
+ * # is equivalent to
1176
+ * q = TypedRangeQuery.new(:date, :lower_exclusive => "0.1")
1177
+ *
1178
+ * # Note that you numbers can be strings or actual numbers
1179
+ * q = TypedRangeQuery.new(:date, :lower => "-12.32", :upper => 0.21)
1180
+ * # is equivalent to
1181
+ * q = TypedRangeQuery.new(:date, :>= => "-12.32", :<= => 0.21)
1182
+ */
1183
+ static VALUE
1184
+ frb_trq_init(VALUE self, VALUE rfield, VALUE roptions)
1185
+ {
1186
+ Query *q;
1187
+ char *lterm = NULL;
1188
+ char *uterm = NULL;
1189
+ bool include_lower = false;
1190
+ bool include_upper = false;
1191
+
1192
+ get_range_params(roptions, &lterm, &uterm, &include_lower, &include_upper);
1193
+ q = trq_new(frb_field(rfield),
1194
+ lterm, uterm,
1195
+ include_lower, include_upper);
1196
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1101
1197
  object_add(q, self);
1102
1198
  return self;
1103
1199
  }
@@ -1116,16 +1212,16 @@ frt_rq_init(VALUE self, VALUE rfield, VALUE roptions)
1116
1212
  * the query it will do anything of value. See PhraseQuery#add_term.
1117
1213
  */
1118
1214
  static VALUE
1119
- frt_phq_init(int argc, VALUE *argv, VALUE self)
1215
+ frb_phq_init(int argc, VALUE *argv, VALUE self)
1120
1216
  {
1121
1217
  VALUE rfield, rslop;
1122
1218
  Query *q;
1123
1219
  rb_scan_args(argc, argv, "11", &rfield, &rslop);
1124
- q = phq_new(frt_field(rfield));
1220
+ q = phq_new(frb_field(rfield));
1125
1221
  if (argc == 2) {
1126
1222
  ((PhraseQuery *)q)->slop = FIX2INT(rslop);
1127
1223
  }
1128
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1224
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1129
1225
  object_add(q, self);
1130
1226
  return self;
1131
1227
  }
@@ -1147,7 +1243,7 @@ frt_phq_init(int argc, VALUE *argv, VALUE self)
1147
1243
  * # doesn't match => "big house"
1148
1244
  */
1149
1245
  static VALUE
1150
- frt_phq_add(int argc, VALUE *argv, VALUE self)
1246
+ frb_phq_add(int argc, VALUE *argv, VALUE self)
1151
1247
  {
1152
1248
  VALUE rterm, rpos_inc;
1153
1249
  int pos_inc = 1;
@@ -1165,15 +1261,15 @@ frt_phq_add(int argc, VALUE *argv, VALUE self)
1165
1261
  {
1166
1262
  int i;
1167
1263
  char *t;
1168
- if (RARRAY(rterm)->len < 1) {
1264
+ if (RARRAY_LEN(rterm) < 1) {
1169
1265
  rb_raise(rb_eArgError, "Cannot add empty array to a "
1170
1266
  "PhraseQuery. You must add either a string or "
1171
1267
  "an array of strings");
1172
1268
  }
1173
- t = StringValuePtr(RARRAY(rterm)->ptr[0]);
1269
+ t = StringValuePtr(RARRAY_PTR(rterm)[0]);
1174
1270
  phq_add_term(q, t, pos_inc);
1175
- for (i = 1; i < RARRAY(rterm)->len; i++) {
1176
- t = StringValuePtr(RARRAY(rterm)->ptr[i]);
1271
+ for (i = 1; i < RARRAY_LEN(rterm); i++) {
1272
+ t = StringValuePtr(RARRAY_PTR(rterm)[i]);
1177
1273
  phq_append_multi_term(q, t);
1178
1274
  }
1179
1275
  break;
@@ -1194,7 +1290,7 @@ frt_phq_add(int argc, VALUE *argv, VALUE self)
1194
1290
  * description for more information on slop
1195
1291
  */
1196
1292
  static VALUE
1197
- frt_phq_get_slop(VALUE self)
1293
+ frb_phq_get_slop(VALUE self)
1198
1294
  {
1199
1295
  GET_Q();
1200
1296
  return INT2FIX(((PhraseQuery *)q)->slop);
@@ -1208,7 +1304,7 @@ frt_phq_get_slop(VALUE self)
1208
1304
  * for more information on slop
1209
1305
  */
1210
1306
  static VALUE
1211
- frt_phq_set_slop(VALUE self, VALUE rslop)
1307
+ frb_phq_set_slop(VALUE self, VALUE rslop)
1212
1308
  {
1213
1309
  GET_Q();
1214
1310
  ((PhraseQuery *)q)->slop = FIX2INT(rslop);
@@ -1238,9 +1334,9 @@ frt_phq_set_slop(VALUE self, VALUE rslop)
1238
1334
  * By default it is set to 512.
1239
1335
  */
1240
1336
  static VALUE
1241
- frt_prq_init(int argc, VALUE *argv, VALUE self)
1337
+ frb_prq_init(int argc, VALUE *argv, VALUE self)
1242
1338
  {
1243
- return frt_mtq_init_specific(argc, argv, self, &prefixq_new);
1339
+ return frb_mtq_init_specific(argc, argv, self, &prefixq_new);
1244
1340
  }
1245
1341
 
1246
1342
  /****************************************************************************
@@ -1268,9 +1364,9 @@ frt_prq_init(int argc, VALUE *argv, VALUE self)
1268
1364
  * query. By default it is set to 512.
1269
1365
  */
1270
1366
  static VALUE
1271
- frt_wcq_init(int argc, VALUE *argv, VALUE self)
1367
+ frb_wcq_init(int argc, VALUE *argv, VALUE self)
1272
1368
  {
1273
- return frt_mtq_init_specific(argc, argv, self, &wcq_new);
1369
+ return frb_mtq_init_specific(argc, argv, self, &wcq_new);
1274
1370
  }
1275
1371
 
1276
1372
  /****************************************************************************
@@ -1320,7 +1416,7 @@ frt_wcq_init(int argc, VALUE *argv, VALUE self)
1320
1416
  * +:min_similarity+ to a very low value.
1321
1417
  */
1322
1418
  static VALUE
1323
- frt_fq_init(int argc, VALUE *argv, VALUE self)
1419
+ frb_fq_init(int argc, VALUE *argv, VALUE self)
1324
1420
  {
1325
1421
  Query *q;
1326
1422
  VALUE rfield, rterm, roptions;
@@ -1362,9 +1458,9 @@ frt_fq_init(int argc, VALUE *argv, VALUE self)
1362
1458
  "%d < 0. :max_terms must be >= 0", max_terms);
1363
1459
  }
1364
1460
 
1365
- q = fuzq_new_conf(frt_field(rfield), StringValuePtr(rterm),
1461
+ q = fuzq_new_conf(frb_field(rfield), StringValuePtr(rterm),
1366
1462
  min_sim, pre_len, max_terms);
1367
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1463
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1368
1464
  object_add(q, self);
1369
1465
  return self;
1370
1466
  }
@@ -1376,7 +1472,7 @@ frt_fq_init(int argc, VALUE *argv, VALUE self)
1376
1472
  * Get the +:prefix_length+ for the query.
1377
1473
  */
1378
1474
  static VALUE
1379
- frt_fq_pre_len(VALUE self)
1475
+ frb_fq_pre_len(VALUE self)
1380
1476
  {
1381
1477
  GET_Q();
1382
1478
  return INT2FIX(((FuzzyQuery *)q)->pre_len);
@@ -1389,7 +1485,7 @@ frt_fq_pre_len(VALUE self)
1389
1485
  * Get the +:min_similarity+ for the query.
1390
1486
  */
1391
1487
  static VALUE
1392
- frt_fq_min_sim(VALUE self)
1488
+ frb_fq_min_sim(VALUE self)
1393
1489
  {
1394
1490
  GET_Q();
1395
1491
  return rb_float_new((double)((FuzzyQuery *)q)->min_sim);
@@ -1402,7 +1498,7 @@ frt_fq_min_sim(VALUE self)
1402
1498
  * Get the default value for +:min_similarity+
1403
1499
  */
1404
1500
  static VALUE
1405
- frt_fq_get_dms(VALUE self)
1501
+ frb_fq_get_dms(VALUE self)
1406
1502
  {
1407
1503
  return rb_cvar_get(cFuzzyQuery, id_default_min_similarity);
1408
1504
  }
@@ -1415,7 +1511,7 @@ extern float qp_default_fuzzy_min_sim;
1415
1511
  * Set the default value for +:min_similarity+
1416
1512
  */
1417
1513
  static VALUE
1418
- frt_fq_set_dms(VALUE self, VALUE val)
1514
+ frb_fq_set_dms(VALUE self, VALUE val)
1419
1515
  {
1420
1516
  double min_sim = NUM2DBL(val);
1421
1517
  if (min_sim >= 1.0) {
@@ -1426,7 +1522,11 @@ frt_fq_set_dms(VALUE self, VALUE val)
1426
1522
  "%f < 0.0. :min_similarity must be > 0.0", min_sim);
1427
1523
  }
1428
1524
  qp_default_fuzzy_min_sim = (float)min_sim;
1525
+ #ifdef FRT_RUBY_VERSION_1_9
1526
+ rb_cvar_set(cFuzzyQuery, id_default_min_similarity, val);
1527
+ #else
1429
1528
  rb_cvar_set(cFuzzyQuery, id_default_min_similarity, val, Qfalse);
1529
+ #endif
1430
1530
  return val;
1431
1531
  }
1432
1532
 
@@ -1437,7 +1537,7 @@ frt_fq_set_dms(VALUE self, VALUE val)
1437
1537
  * Get the default value for +:prefix_length+
1438
1538
  */
1439
1539
  static VALUE
1440
- frt_fq_get_dpl(VALUE self)
1540
+ frb_fq_get_dpl(VALUE self)
1441
1541
  {
1442
1542
  return rb_cvar_get(cFuzzyQuery, id_default_prefix_length);
1443
1543
  }
@@ -1450,7 +1550,7 @@ extern int qp_default_fuzzy_pre_len;
1450
1550
  * Set the default value for +:prefix_length+
1451
1551
  */
1452
1552
  static VALUE
1453
- frt_fq_set_dpl(VALUE self, VALUE val)
1553
+ frb_fq_set_dpl(VALUE self, VALUE val)
1454
1554
  {
1455
1555
  int pre_len = FIX2INT(val);
1456
1556
  if (pre_len < 0) {
@@ -1458,7 +1558,11 @@ frt_fq_set_dpl(VALUE self, VALUE val)
1458
1558
  "%d < 0. :prefix_length must be >= 0", pre_len);
1459
1559
  }
1460
1560
  qp_default_fuzzy_pre_len = pre_len;
1561
+ #ifdef FRT_RUBY_VERSION_1_9
1562
+ rb_cvar_set(cFuzzyQuery, id_default_prefix_length, val);
1563
+ #else
1461
1564
  rb_cvar_set(cFuzzyQuery, id_default_prefix_length, val, Qfalse);
1565
+ #endif
1462
1566
  return val;
1463
1567
  }
1464
1568
 
@@ -1470,10 +1574,10 @@ frt_fq_set_dpl(VALUE self, VALUE val)
1470
1574
  ****************************************************************************/
1471
1575
 
1472
1576
  static VALUE
1473
- frt_maq_alloc(VALUE klass)
1577
+ frb_maq_alloc(VALUE klass)
1474
1578
  {
1475
1579
  Query *q = maq_new();
1476
- VALUE self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
1580
+ VALUE self = Data_Wrap_Struct(klass, NULL, &frb_q_free, q);
1477
1581
  object_add(q, self);
1478
1582
  return self;
1479
1583
  }
@@ -1485,7 +1589,7 @@ frt_maq_alloc(VALUE klass)
1485
1589
  * Create a query which matches all documents.
1486
1590
  */
1487
1591
  static VALUE
1488
- frt_maq_init(VALUE self)
1592
+ frb_maq_init(VALUE self)
1489
1593
  {
1490
1594
  return self;
1491
1595
  }
@@ -1504,14 +1608,14 @@ frt_maq_init(VALUE self)
1504
1608
  * each document a constant score.
1505
1609
  */
1506
1610
  static VALUE
1507
- frt_csq_init(VALUE self, VALUE rfilter)
1611
+ frb_csq_init(VALUE self, VALUE rfilter)
1508
1612
  {
1509
1613
  Query *q;
1510
1614
  Filter *filter;
1511
1615
  Data_Get_Struct(rfilter, Filter, filter);
1512
1616
  q = csq_new(filter);
1513
1617
 
1514
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1618
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1515
1619
  object_add(q, self);
1516
1620
  return self;
1517
1621
  }
@@ -1523,11 +1627,11 @@ frt_csq_init(VALUE self, VALUE rfilter)
1523
1627
  ****************************************************************************/
1524
1628
 
1525
1629
  static void
1526
- frt_fqq_mark(void *p)
1630
+ frb_fqq_mark(void *p)
1527
1631
  {
1528
1632
  FilteredQuery *fq = (FilteredQuery *)p;
1529
- frt_gc_mark(fq->query);
1530
- frt_gc_mark(fq->filter);
1633
+ frb_gc_mark(fq->query);
1634
+ frb_gc_mark(fq->filter);
1531
1635
  }
1532
1636
 
1533
1637
  /*
@@ -1537,7 +1641,7 @@ frt_fqq_mark(void *p)
1537
1641
  * Create a new FilteredQuery which filters +query+ with +filter+.
1538
1642
  */
1539
1643
  static VALUE
1540
- frt_fqq_init(VALUE self, VALUE rquery, VALUE rfilter)
1644
+ frb_fqq_init(VALUE self, VALUE rquery, VALUE rfilter)
1541
1645
  {
1542
1646
  Query *sq, *q;
1543
1647
  Filter *f;
@@ -1546,7 +1650,7 @@ frt_fqq_init(VALUE self, VALUE rquery, VALUE rfilter)
1546
1650
  q = fq_new(sq, f);
1547
1651
  REF(sq);
1548
1652
  REF(f);
1549
- Frt_Wrap_Struct(self, &frt_fqq_mark, &frt_q_free, q);
1653
+ Frt_Wrap_Struct(self, &frb_fqq_mark, &frb_q_free, q);
1550
1654
  object_add(q, self);
1551
1655
  return self;
1552
1656
  }
@@ -1565,10 +1669,10 @@ frt_fqq_init(VALUE self, VALUE rquery, VALUE rfilter)
1565
1669
  * +term+ in the field +field+.
1566
1670
  */
1567
1671
  static VALUE
1568
- frt_spantq_init(VALUE self, VALUE rfield, VALUE rterm)
1672
+ frb_spantq_init(VALUE self, VALUE rfield, VALUE rterm)
1569
1673
  {
1570
- Query *q = spantq_new(frt_field(rfield), StringValuePtr(rterm));
1571
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1674
+ Query *q = spantq_new(frb_field(rfield), StringValuePtr(rterm));
1675
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1572
1676
  object_add(q, self);
1573
1677
  return self;
1574
1678
  }
@@ -1587,14 +1691,14 @@ frt_spantq_init(VALUE self, VALUE rfield, VALUE rterm)
1587
1691
  * +terms+ in the field +field+. +terms+ should be an array of Strings.
1588
1692
  */
1589
1693
  static VALUE
1590
- frt_spanmtq_init(VALUE self, VALUE rfield, VALUE rterms)
1694
+ frb_spanmtq_init(VALUE self, VALUE rfield, VALUE rterms)
1591
1695
  {
1592
- Query *q = spanmtq_new(frt_field(rfield));
1696
+ Query *q = spanmtq_new(frb_field(rfield));
1593
1697
  int i;
1594
- for (i = RARRAY(rterms)->len - 1; i >= 0; i--) {
1595
- spanmtq_add_term(q, StringValuePtr(RARRAY(rterms)->ptr[i]));
1698
+ for (i = RARRAY_LEN(rterms) - 1; i >= 0; i--) {
1699
+ spanmtq_add_term(q, StringValuePtr(RARRAY_PTR(rterms)[i]));
1596
1700
  }
1597
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1701
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1598
1702
  object_add(q, self);
1599
1703
  return self;
1600
1704
  }
@@ -1613,7 +1717,7 @@ frt_spanmtq_init(VALUE self, VALUE rfield, VALUE rterms)
1613
1717
  * +prefix+ in the field +field+.
1614
1718
  */
1615
1719
  static VALUE
1616
- frt_spanprq_init(int argc, VALUE *argv, VALUE self)
1720
+ frb_spanprq_init(int argc, VALUE *argv, VALUE self)
1617
1721
  {
1618
1722
  VALUE rfield, rprefix, rmax_terms;
1619
1723
  int max_terms = SPAN_PREFIX_QUERY_MAX_TERMS;
@@ -1621,9 +1725,9 @@ frt_spanprq_init(int argc, VALUE *argv, VALUE self)
1621
1725
  if (rb_scan_args(argc, argv, "21", &rfield, &rprefix, &rmax_terms) == 3) {
1622
1726
  max_terms = FIX2INT(rmax_terms);
1623
1727
  }
1624
- q = spanprq_new(frt_field(rfield), StringValuePtr(rprefix));
1728
+ q = spanprq_new(frb_field(rfield), StringValuePtr(rprefix));
1625
1729
  ((SpanPrefixQuery *)q)->max_terms = max_terms;
1626
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1730
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1627
1731
  object_add(q, self);
1628
1732
  return self;
1629
1733
  }
@@ -1643,13 +1747,13 @@ frt_spanprq_init(int argc, VALUE *argv, VALUE self)
1643
1747
  * field
1644
1748
  */
1645
1749
  static VALUE
1646
- frt_spanfq_init(VALUE self, VALUE rmatch, VALUE rend)
1750
+ frb_spanfq_init(VALUE self, VALUE rmatch, VALUE rend)
1647
1751
  {
1648
1752
  Query *q;
1649
1753
  Query *match;
1650
1754
  Data_Get_Struct(rmatch, Query, match);
1651
1755
  q = spanfq_new(match, FIX2INT(rend));
1652
- Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
1756
+ Frt_Wrap_Struct(self, NULL, &frb_q_free, q);
1653
1757
  object_add(q, self);
1654
1758
  return self;
1655
1759
  }
@@ -1661,12 +1765,12 @@ frt_spanfq_init(VALUE self, VALUE rmatch, VALUE rend)
1661
1765
  ****************************************************************************/
1662
1766
 
1663
1767
  static void
1664
- frt_spannq_mark(void *p)
1768
+ frb_spannq_mark(void *p)
1665
1769
  {
1666
1770
  int i;
1667
1771
  SpanNearQuery *snq = (SpanNearQuery *)p;
1668
1772
  for (i = 0; i < snq->c_cnt; i++) {
1669
- frt_gc_mark(snq->clauses[i]);
1773
+ frb_gc_mark(snq->clauses[i]);
1670
1774
  }
1671
1775
  }
1672
1776
 
@@ -1693,7 +1797,7 @@ frt_spannq_mark(void *p)
1693
1797
  * set to 0, this parameter will make no difference.
1694
1798
  */
1695
1799
  static VALUE
1696
- frt_spannq_init(int argc, VALUE *argv, VALUE self)
1800
+ frb_spannq_init(int argc, VALUE *argv, VALUE self)
1697
1801
  {
1698
1802
  Query *q;
1699
1803
  VALUE roptions;
@@ -1716,14 +1820,14 @@ frt_spannq_init(int argc, VALUE *argv, VALUE self)
1716
1820
  int i;
1717
1821
  Query *clause;
1718
1822
  Check_Type(v, T_ARRAY);
1719
- for (i = 0; i < RARRAY(v)->len; i++) {
1720
- Data_Get_Struct(RARRAY(v)->ptr[i], Query, clause);
1823
+ for (i = 0; i < RARRAY_LEN(v); i++) {
1824
+ Data_Get_Struct(RARRAY_PTR(v)[i], Query, clause);
1721
1825
  spannq_add_clause(q, clause);
1722
1826
  }
1723
1827
  }
1724
1828
  }
1725
1829
 
1726
- Frt_Wrap_Struct(self, &frt_spannq_mark, &frt_q_free, q);
1830
+ Frt_Wrap_Struct(self, &frb_spannq_mark, &frb_q_free, q);
1727
1831
  object_add(q, self);
1728
1832
  return self;
1729
1833
  }
@@ -1738,7 +1842,7 @@ frt_spannq_init(int argc, VALUE *argv, VALUE self)
1738
1842
  * must be SpanQueries, not other types of query.
1739
1843
  */
1740
1844
  static VALUE
1741
- frt_spannq_add(VALUE self, VALUE rclause)
1845
+ frb_spannq_add(VALUE self, VALUE rclause)
1742
1846
  {
1743
1847
  GET_Q();
1744
1848
  Query *clause;
@@ -1754,12 +1858,12 @@ frt_spannq_add(VALUE self, VALUE rclause)
1754
1858
  ****************************************************************************/
1755
1859
 
1756
1860
  static void
1757
- frt_spanoq_mark(void *p)
1861
+ frb_spanoq_mark(void *p)
1758
1862
  {
1759
1863
  int i;
1760
1864
  SpanOrQuery *soq = (SpanOrQuery *)p;
1761
1865
  for (i = 0; i < soq->c_cnt; i++) {
1762
- frt_gc_mark(soq->clauses[i]);
1866
+ frb_gc_mark(soq->clauses[i]);
1763
1867
  }
1764
1868
  }
1765
1869
 
@@ -1772,7 +1876,7 @@ frt_spanoq_mark(void *p)
1772
1876
  * passed to other SpanQuerys like SpanNearQuery.
1773
1877
  */
1774
1878
  static VALUE
1775
- frt_spanoq_init(int argc, VALUE *argv, VALUE self)
1879
+ frb_spanoq_init(int argc, VALUE *argv, VALUE self)
1776
1880
  {
1777
1881
  Query *q;
1778
1882
  VALUE rclauses;
@@ -1782,12 +1886,12 @@ frt_spanoq_init(int argc, VALUE *argv, VALUE self)
1782
1886
  int i;
1783
1887
  Query *clause;
1784
1888
  Check_Type(rclauses, T_ARRAY);
1785
- for (i = 0; i < RARRAY(rclauses)->len; i++) {
1786
- Data_Get_Struct(RARRAY(rclauses)->ptr[i], Query, clause);
1889
+ for (i = 0; i < RARRAY_LEN(rclauses); i++) {
1890
+ Data_Get_Struct(RARRAY_PTR(rclauses)[i], Query, clause);
1787
1891
  spanoq_add_clause(q, clause);
1788
1892
  }
1789
1893
  }
1790
- Frt_Wrap_Struct(self, &frt_spanoq_mark, &frt_q_free, q);
1894
+ Frt_Wrap_Struct(self, &frb_spanoq_mark, &frb_q_free, q);
1791
1895
  object_add(q, self);
1792
1896
  return self;
1793
1897
  }
@@ -1801,7 +1905,7 @@ frt_spanoq_init(int argc, VALUE *argv, VALUE self)
1801
1905
  * not other types of query.
1802
1906
  */
1803
1907
  static VALUE
1804
- frt_spanoq_add(VALUE self, VALUE rclause)
1908
+ frb_spanoq_add(VALUE self, VALUE rclause)
1805
1909
  {
1806
1910
  GET_Q();
1807
1911
  Query *clause;
@@ -1817,11 +1921,11 @@ frt_spanoq_add(VALUE self, VALUE rclause)
1817
1921
  ****************************************************************************/
1818
1922
 
1819
1923
  static void
1820
- frt_spanxq_mark(void *p)
1924
+ frb_spanxq_mark(void *p)
1821
1925
  {
1822
1926
  SpanNotQuery *sxq = (SpanNotQuery *)p;
1823
- frt_gc_mark(sxq->inc);
1824
- frt_gc_mark(sxq->exc);
1927
+ frb_gc_mark(sxq->inc);
1928
+ frb_gc_mark(sxq->exc);
1825
1929
  }
1826
1930
 
1827
1931
  /*
@@ -1832,13 +1936,13 @@ frt_spanxq_mark(void *p)
1832
1936
  * +include_query+ and don't match +exclude_query+.
1833
1937
  */
1834
1938
  static VALUE
1835
- frt_spanxq_init(VALUE self, VALUE rinc, VALUE rexc)
1939
+ frb_spanxq_init(VALUE self, VALUE rinc, VALUE rexc)
1836
1940
  {
1837
1941
  Query *q;
1838
1942
  Check_Type(rinc, T_DATA);
1839
1943
  Check_Type(rexc, T_DATA);
1840
1944
  q = spanxq_new(DATA_PTR(rinc), DATA_PTR(rexc));
1841
- Frt_Wrap_Struct(self, &frt_spanxq_mark, &frt_q_free, q);
1945
+ Frt_Wrap_Struct(self, &frb_spanxq_mark, &frb_q_free, q);
1842
1946
  object_add(q, self);
1843
1947
  return self;
1844
1948
  }
@@ -1850,7 +1954,7 @@ frt_spanxq_init(VALUE self, VALUE rinc, VALUE rexc)
1850
1954
  ****************************************************************************/
1851
1955
 
1852
1956
  static void
1853
- frt_f_free(void *p)
1957
+ frb_f_free(void *p)
1854
1958
  {
1855
1959
  object_del(p);
1856
1960
  filt_deref((Filter *)p);
@@ -1866,7 +1970,7 @@ frt_f_free(void *p)
1866
1970
  * method was called on.
1867
1971
  */
1868
1972
  static VALUE
1869
- frt_f_to_s(VALUE self)
1973
+ frb_f_to_s(VALUE self)
1870
1974
  {
1871
1975
  VALUE rstr;
1872
1976
  char *str;
@@ -1877,7 +1981,7 @@ frt_f_to_s(VALUE self)
1877
1981
  return rstr;
1878
1982
  }
1879
1983
 
1880
- extern VALUE frt_get_bv(BitVector *bv);
1984
+ extern VALUE frb_get_bv(BitVector *bv);
1881
1985
 
1882
1986
  /*
1883
1987
  * call-seq:
@@ -1887,14 +1991,14 @@ extern VALUE frt_get_bv(BitVector *bv);
1887
1991
  * to group filters or apply filters to other filters.
1888
1992
  */
1889
1993
  static VALUE
1890
- frt_f_get_bits(VALUE self, VALUE rindex_reader)
1994
+ frb_f_get_bits(VALUE self, VALUE rindex_reader)
1891
1995
  {
1892
1996
  BitVector *bv;
1893
1997
  IndexReader *ir;
1894
1998
  GET_F();
1895
1999
  Data_Get_Struct(rindex_reader, IndexReader, ir);
1896
2000
  bv = filt_get_bv(f, ir);
1897
- return frt_get_bv(bv);
2001
+ return frb_get_bv(bv);
1898
2002
  }
1899
2003
 
1900
2004
  /****************************************************************************
@@ -1927,7 +2031,7 @@ frt_f_get_bits(VALUE self, VALUE rindex_reader)
1927
2031
  * f = RangeFilter.new(:date, :>= => "200501", :<= => 200502)
1928
2032
  */
1929
2033
  static VALUE
1930
- frt_rf_init(VALUE self, VALUE rfield, VALUE roptions)
2034
+ frb_rf_init(VALUE self, VALUE rfield, VALUE roptions)
1931
2035
  {
1932
2036
  Filter *f;
1933
2037
  char *lterm = NULL;
@@ -1936,9 +2040,56 @@ frt_rf_init(VALUE self, VALUE rfield, VALUE roptions)
1936
2040
  bool include_upper = false;
1937
2041
 
1938
2042
  get_range_params(roptions, &lterm, &uterm, &include_lower, &include_upper);
1939
- f = rfilt_new(frt_field(rfield), lterm, uterm,
2043
+ f = rfilt_new(frb_field(rfield), lterm, uterm,
1940
2044
  include_lower, include_upper);
1941
- Frt_Wrap_Struct(self, NULL, &frt_f_free, f);
2045
+ Frt_Wrap_Struct(self, NULL, &frb_f_free, f);
2046
+ object_add(f, self);
2047
+ return self;
2048
+ }
2049
+
2050
+ /****************************************************************************
2051
+ *
2052
+ * TypedRangeFilter Methods
2053
+ *
2054
+ ****************************************************************************/
2055
+
2056
+
2057
+ /*
2058
+ * call-seq:
2059
+ * TypedRangeFilter.new(field, options = {}) -> range_query
2060
+ *
2061
+ * Create a new TypedRangeFilter on field +field+. There are two ways to
2062
+ * build a range filter. With the old-style options; +:lower+, +:upper+,
2063
+ * +:include_lower+ and +:include_upper+ or the new style options; +:<+,
2064
+ * +:<=+, +:>+ and +:>=+. The options' names should speak for themselves.
2065
+ * In the old-style options, limits are inclusive by default.
2066
+ *
2067
+ * == Examples
2068
+ *
2069
+ * f = TypedRangeFilter.new(:date, :lower => "0.1", :include_lower => false)
2070
+ * # is equivalent to
2071
+ * f = TypedRangeFilter.new(:date, :< => "0.1")
2072
+ * # is equivalent to
2073
+ * f = TypedRangeFilter.new(:date, :lower_exclusive => "0.1")
2074
+ *
2075
+ * # Note that you numbers can be strings or actual numbers
2076
+ * f = TypedRangeFilter.new(:date, :lower => "-132.2", :upper => -1.4)
2077
+ * # is equivalent to
2078
+ * f = TypedRangeFilter.new(:date, :>= => "-132.2", :<= => -1.4)
2079
+ */
2080
+ static VALUE
2081
+ frb_trf_init(VALUE self, VALUE rfield, VALUE roptions)
2082
+ {
2083
+ Filter *f;
2084
+ char *lterm = NULL;
2085
+ char *uterm = NULL;
2086
+ bool include_lower = false;
2087
+ bool include_upper = false;
2088
+
2089
+ get_range_params(roptions, &lterm, &uterm, &include_lower, &include_upper);
2090
+ f = trfilt_new(frb_field(rfield), lterm, uterm,
2091
+ include_lower, include_upper);
2092
+ Frt_Wrap_Struct(self, NULL, &frb_f_free, f);
1942
2093
  object_add(f, self);
1943
2094
  return self;
1944
2095
  }
@@ -1956,13 +2107,13 @@ frt_rf_init(VALUE self, VALUE rfield, VALUE roptions)
1956
2107
  * Create a new QueryFilter which applies the query +query+.
1957
2108
  */
1958
2109
  static VALUE
1959
- frt_qf_init(VALUE self, VALUE rquery)
2110
+ frb_qf_init(VALUE self, VALUE rquery)
1960
2111
  {
1961
2112
  Query *q;
1962
2113
  Filter *f;
1963
2114
  Data_Get_Struct(rquery, Query, q);
1964
2115
  f = qfilt_new(q);
1965
- Frt_Wrap_Struct(self, NULL, &frt_f_free, f);
2116
+ Frt_Wrap_Struct(self, NULL, &frb_f_free, f);
1966
2117
  object_add(f, self);
1967
2118
  return self;
1968
2119
  }
@@ -1974,18 +2125,18 @@ frt_qf_init(VALUE self, VALUE rquery)
1974
2125
  ****************************************************************************/
1975
2126
 
1976
2127
  static void
1977
- frt_sf_free(void *p)
2128
+ frb_sf_free(void *p)
1978
2129
  {
1979
2130
  object_del(p);
1980
2131
  sort_field_destroy((SortField *)p);
1981
2132
  }
1982
2133
 
1983
2134
  static VALUE
1984
- frt_get_sf(SortField *sf)
2135
+ frb_get_sf(SortField *sf)
1985
2136
  {
1986
2137
  VALUE self = object_get(sf);
1987
2138
  if (self == Qnil) {
1988
- self = Data_Wrap_Struct(cSortField, NULL, &frt_sf_free, sf);
2139
+ self = Data_Wrap_Struct(cSortField, NULL, &frb_sf_free, sf);
1989
2140
  object_add(sf, self);
1990
2141
  }
1991
2142
  return self;
@@ -2038,14 +2189,14 @@ get_sort_type(VALUE rtype)
2038
2189
  * sort.
2039
2190
  */
2040
2191
  static VALUE
2041
- frt_sf_init(int argc, VALUE *argv, VALUE self)
2192
+ frb_sf_init(int argc, VALUE *argv, VALUE self)
2042
2193
  {
2043
2194
  SortField *sf;
2044
2195
  VALUE rfield, roptions;
2045
2196
  VALUE rval;
2046
2197
  int type = SORT_TYPE_AUTO;
2047
2198
  int is_reverse = false;
2048
- char *field;
2199
+ Symbol field;
2049
2200
 
2050
2201
  if (rb_scan_args(argc, argv, "11", &rfield, &roptions) == 2) {
2051
2202
  if (Qnil != (rval = rb_hash_aref(roptions, sym_type))) {
@@ -2059,14 +2210,14 @@ frt_sf_init(int argc, VALUE *argv, VALUE self)
2059
2210
  }
2060
2211
  }
2061
2212
  if (NIL_P(rfield)) rb_raise(rb_eArgError, "must pass a valid field name");
2062
- field = frt_field(rfield);
2213
+ field = frb_field(rfield);
2063
2214
 
2064
2215
  sf = sort_field_new(field, type, is_reverse);
2065
- if (sf->field == NULL && field) {
2066
- sf->field = estrdup(field);
2216
+ if (sf->field == NULL) {
2217
+ sf->field = field;
2067
2218
  }
2068
2219
 
2069
- Frt_Wrap_Struct(self, NULL, &frt_sf_free, sf);
2220
+ Frt_Wrap_Struct(self, NULL, &frb_sf_free, sf);
2070
2221
  object_add(sf, self);
2071
2222
  return self;
2072
2223
  }
@@ -2081,7 +2232,7 @@ frt_sf_init(int argc, VALUE *argv, VALUE self)
2081
2232
  * when you create the sort_field.
2082
2233
  */
2083
2234
  static VALUE
2084
- frt_sf_is_reverse(VALUE self)
2235
+ frb_sf_is_reverse(VALUE self)
2085
2236
  {
2086
2237
  GET_SF();
2087
2238
  return sf->reverse ? Qtrue : Qfalse;
@@ -2094,10 +2245,10 @@ frt_sf_is_reverse(VALUE self)
2094
2245
  * Returns the name of the field to be sorted.
2095
2246
  */
2096
2247
  static VALUE
2097
- frt_sf_get_name(VALUE self)
2248
+ frb_sf_get_name(VALUE self)
2098
2249
  {
2099
2250
  GET_SF();
2100
- return sf->field ? ID2SYM(rb_intern(sf->field)) : Qnil;
2251
+ return sf->field ? FSYM2SYM(sf->field) : Qnil;
2101
2252
  }
2102
2253
 
2103
2254
  /*
@@ -2108,7 +2259,7 @@ frt_sf_get_name(VALUE self)
2108
2259
  * +:string+, +:byte+, +:doc_id+ or +:score+.
2109
2260
  */
2110
2261
  static VALUE
2111
- frt_sf_get_type(VALUE self)
2262
+ frb_sf_get_type(VALUE self)
2112
2263
  {
2113
2264
  GET_SF();
2114
2265
  switch (sf->type) {
@@ -2130,7 +2281,7 @@ frt_sf_get_type(VALUE self)
2130
2281
  * TODO: currently unsupported
2131
2282
  */
2132
2283
  static VALUE
2133
- frt_sf_get_comparator(VALUE self)
2284
+ frb_sf_get_comparator(VALUE self)
2134
2285
  {
2135
2286
  return Qnil;
2136
2287
  }
@@ -2142,7 +2293,7 @@ frt_sf_get_comparator(VALUE self)
2142
2293
  * Return a human readable string describing this +sort_field+.
2143
2294
  */
2144
2295
  static VALUE
2145
- frt_sf_to_s(VALUE self)
2296
+ frb_sf_to_s(VALUE self)
2146
2297
  {
2147
2298
  GET_SF();
2148
2299
  char *str = sort_field_to_s(sf);
@@ -2158,7 +2309,7 @@ frt_sf_to_s(VALUE self)
2158
2309
  ****************************************************************************/
2159
2310
 
2160
2311
  static void
2161
- frt_sort_free(void *p)
2312
+ frb_sort_free(void *p)
2162
2313
  {
2163
2314
  Sort *sort = (Sort *)p;
2164
2315
  object_del(sort);
@@ -2166,28 +2317,28 @@ frt_sort_free(void *p)
2166
2317
  }
2167
2318
 
2168
2319
  static void
2169
- frt_sort_mark(void *p)
2320
+ frb_sort_mark(void *p)
2170
2321
  {
2171
2322
  Sort *sort = (Sort *)p;
2172
2323
  int i;
2173
2324
  for (i = 0; i < sort->size; i++) {
2174
- frt_gc_mark(sort->sort_fields[i]);
2325
+ frb_gc_mark(sort->sort_fields[i]);
2175
2326
  }
2176
2327
  }
2177
2328
 
2178
2329
  static VALUE
2179
- frt_sort_alloc(VALUE klass)
2330
+ frb_sort_alloc(VALUE klass)
2180
2331
  {
2181
2332
  VALUE self;
2182
2333
  Sort *sort = sort_new();
2183
2334
  sort->destroy_all = false;
2184
- self = Data_Wrap_Struct(klass, &frt_sort_mark, &frt_sort_free, sort);
2335
+ self = Data_Wrap_Struct(klass, &frb_sort_mark, &frb_sort_free, sort);
2185
2336
  object_add(sort, self);
2186
2337
  return self;
2187
2338
  }
2188
2339
 
2189
2340
  static void
2190
- frt_parse_sort_str(Sort *sort, char *xsort_str)
2341
+ frb_parse_sort_str(Sort *sort, char *xsort_str)
2191
2342
  {
2192
2343
  SortField *sf;
2193
2344
  char *comma, *end, *e, *s;
@@ -2219,9 +2370,9 @@ frt_parse_sort_str(Sort *sort, char *xsort_str)
2219
2370
  } else if (strcmp("DOC_ID", s) == 0) {
2220
2371
  sf = sort_field_doc_new(reverse);
2221
2372
  } else {
2222
- sf = sort_field_auto_new(s, reverse);
2373
+ sf = sort_field_auto_new(I(s), reverse);
2223
2374
  }
2224
- frt_get_sf(sf);
2375
+ frb_get_sf(sf);
2225
2376
  sort_add_sort_field(sort, sf);
2226
2377
  s = comma + 1;
2227
2378
  }
@@ -2229,7 +2380,7 @@ frt_parse_sort_str(Sort *sort, char *xsort_str)
2229
2380
  }
2230
2381
 
2231
2382
  static void
2232
- frt_sort_add(Sort *sort, VALUE rsf, bool reverse)
2383
+ frb_sort_add(Sort *sort, VALUE rsf, bool reverse)
2233
2384
  {
2234
2385
  SortField *sf;
2235
2386
  switch (TYPE(rsf)) {
@@ -2239,15 +2390,14 @@ frt_sort_add(Sort *sort, VALUE rsf, bool reverse)
2239
2390
  sort_add_sort_field(sort, sf);
2240
2391
  break;
2241
2392
  case T_SYMBOL:
2242
- rsf = rb_obj_as_string(rsf);
2243
- sf = sort_field_auto_new(rs2s(rsf), reverse);
2393
+ sf = sort_field_auto_new(frb_field(rsf), reverse);
2244
2394
  /* need to give it a ruby object so it'll be freed when the
2245
2395
  * sort is garbage collected */
2246
- rsf = frt_get_sf(sf);
2396
+ rsf = frb_get_sf(sf);
2247
2397
  sort_add_sort_field(sort, sf);
2248
2398
  break;
2249
2399
  case T_STRING:
2250
- frt_parse_sort_str(sort, rs2s(rsf));
2400
+ frb_parse_sort_str(sort, rs2s(rsf));
2251
2401
  break;
2252
2402
  default:
2253
2403
  rb_raise(rb_eArgError, "Unknown SortField Type");
@@ -2265,7 +2415,7 @@ frt_sort_add(Sort *sort, VALUE rsf, bool reverse)
2265
2415
  * to their natural order again. By default
2266
2416
  */
2267
2417
  static VALUE
2268
- frt_sort_init(int argc, VALUE *argv, VALUE self)
2418
+ frb_sort_init(int argc, VALUE *argv, VALUE self)
2269
2419
  {
2270
2420
  int i;
2271
2421
  VALUE rfields, rreverse;
@@ -2277,11 +2427,11 @@ frt_sort_init(int argc, VALUE *argv, VALUE self)
2277
2427
  case 1:
2278
2428
  if (TYPE(rfields) == T_ARRAY) {
2279
2429
  int i;
2280
- for (i = 0; i < RARRAY(rfields)->len; i++) {
2281
- frt_sort_add(sort, RARRAY(rfields)->ptr[i], reverse);
2430
+ for (i = 0; i < RARRAY_LEN(rfields); i++) {
2431
+ frb_sort_add(sort, RARRAY_PTR(rfields)[i], reverse);
2282
2432
  }
2283
2433
  } else {
2284
- frt_sort_add(sort, rfields, reverse);
2434
+ frb_sort_add(sort, rfields, reverse);
2285
2435
  }
2286
2436
  for (i = 0; i < sort->size; i++) {
2287
2437
  if (sort->sort_fields[i] == &SORT_FIELD_DOC) has_sfd = true;
@@ -2305,7 +2455,7 @@ frt_sort_init(int argc, VALUE *argv, VALUE self)
2305
2455
  * Returns an array of the SortFields held by the Sort object.
2306
2456
  */
2307
2457
  static VALUE
2308
- frt_sort_get_fields(VALUE self)
2458
+ frb_sort_get_fields(VALUE self)
2309
2459
  {
2310
2460
  GET_SORT();
2311
2461
  VALUE rfields = rb_ary_new2(sort->size);
@@ -2324,7 +2474,7 @@ frt_sort_get_fields(VALUE self)
2324
2474
  * Returns a human readable string representing the sort object.
2325
2475
  */
2326
2476
  static VALUE
2327
- frt_sort_to_s(VALUE self)
2477
+ frb_sort_to_s(VALUE self)
2328
2478
  {
2329
2479
  GET_SORT();
2330
2480
  char *str = sort_to_s(sort);
@@ -2340,7 +2490,7 @@ frt_sort_to_s(VALUE self)
2340
2490
  ****************************************************************************/
2341
2491
 
2342
2492
  static void
2343
- frt_sea_free(void *p)
2493
+ frb_sea_free(void *p)
2344
2494
  {
2345
2495
  Searcher *sea = (Searcher *)p;
2346
2496
  object_del(sea);
@@ -2357,7 +2507,7 @@ frt_sea_free(void *p)
2357
2507
  * call this method explicitly.
2358
2508
  */
2359
2509
  static VALUE
2360
- frt_sea_close(VALUE self)
2510
+ frb_sea_close(VALUE self)
2361
2511
  {
2362
2512
  GET_SEA();
2363
2513
  Frt_Unwrap_Struct(self);
@@ -2373,7 +2523,7 @@ frt_sea_close(VALUE self)
2373
2523
  * Return the IndexReader wrapped by this searcher.
2374
2524
  */
2375
2525
  static VALUE
2376
- frt_sea_get_reader(VALUE self, VALUE rterm)
2526
+ frb_sea_get_reader(VALUE self, VALUE rterm)
2377
2527
  {
2378
2528
  GET_SEA();
2379
2529
  return object_get(((IndexSearcher *)sea)->ir);
@@ -2387,11 +2537,11 @@ frt_sea_get_reader(VALUE self, VALUE rterm)
2387
2537
  * field +field+.
2388
2538
  */
2389
2539
  static VALUE
2390
- frt_sea_doc_freq(VALUE self, VALUE rfield, VALUE rterm)
2540
+ frb_sea_doc_freq(VALUE self, VALUE rfield, VALUE rterm)
2391
2541
  {
2392
2542
  GET_SEA();
2393
2543
  return INT2FIX(sea->doc_freq(sea,
2394
- frt_field(rfield),
2544
+ frb_field(rfield),
2395
2545
  StringValuePtr(rterm)));
2396
2546
  }
2397
2547
 
@@ -2405,10 +2555,10 @@ frt_sea_doc_freq(VALUE self, VALUE rfield, VALUE rterm)
2405
2555
  * which are returned by the Searchers search methods.
2406
2556
  */
2407
2557
  static VALUE
2408
- frt_sea_doc(VALUE self, VALUE rdoc_id)
2558
+ frb_sea_doc(VALUE self, VALUE rdoc_id)
2409
2559
  {
2410
2560
  GET_SEA();
2411
- return frt_get_lazy_doc(sea->get_lazy_doc(sea, FIX2INT(rdoc_id)));
2561
+ return frb_get_lazy_doc(sea->get_lazy_doc(sea, FIX2INT(rdoc_id)));
2412
2562
  }
2413
2563
 
2414
2564
  /*
@@ -2421,19 +2571,31 @@ frt_sea_doc(VALUE self, VALUE rdoc_id)
2421
2571
  * in the index.
2422
2572
  */
2423
2573
  static VALUE
2424
- frt_sea_max_doc(VALUE self)
2574
+ frb_sea_max_doc(VALUE self)
2425
2575
  {
2426
2576
  GET_SEA();
2427
2577
  return INT2FIX(sea->max_doc(sea));
2428
2578
  }
2429
2579
 
2430
- static bool
2431
- call_filter_proc(int doc_id, float score, Searcher *self)
2432
- {
2433
- return RTEST(rb_funcall((VALUE)self->arg, id_call, 3,
2434
- INT2FIX(doc_id),
2435
- rb_float_new((double)score),
2436
- object_get(self)));
2580
+ static float
2581
+ call_filter_proc(int doc_id, float score, Searcher *self, void *arg)
2582
+ {
2583
+ VALUE val = rb_funcall((VALUE)arg, id_call, 3,
2584
+ INT2FIX(doc_id),
2585
+ rb_float_new((double)score),
2586
+ object_get(self));
2587
+ switch (TYPE(val)) {
2588
+ case T_NIL:
2589
+ case T_FALSE:
2590
+ return 0.0f;
2591
+ case T_FLOAT:
2592
+ {
2593
+ double d = NUM2DBL(val);
2594
+ return (d >= 0.0 && d <= 1.0) ? (float)d : 1.0f;
2595
+ }
2596
+ default:
2597
+ return 1.0f;
2598
+ }
2437
2599
  }
2438
2600
 
2439
2601
  typedef struct CWrappedFilter
@@ -2466,25 +2628,25 @@ cwfilt_get_bv_i(Filter *filt, IndexReader *ir)
2466
2628
  }
2467
2629
 
2468
2630
  Filter *
2469
- frt_get_cwrapped_filter(VALUE rval)
2631
+ frb_get_cwrapped_filter(VALUE rval)
2470
2632
  {
2471
2633
  Filter *filter;
2472
- if (frt_is_cclass(rval) && DATA_PTR(rval)) {
2634
+ if (frb_is_cclass(rval) && DATA_PTR(rval)) {
2473
2635
  Data_Get_Struct(rval, Filter, filter);
2474
2636
  REF(filter);
2475
2637
  }
2476
2638
  else {
2477
- filter = filt_create(sizeof(CWrappedFilter), "CWrappedFilter");
2478
- filter->hash = &cwfilt_hash;
2479
- filter->eq = &cwfilt_eq;
2480
- filter->get_bv_i = &cwfilt_get_bv_i;
2639
+ filter = filt_new(CWrappedFilter);
2640
+ filter->hash = &cwfilt_hash;
2641
+ filter->eq = &cwfilt_eq;
2642
+ filter->get_bv_i = &cwfilt_get_bv_i;
2481
2643
  CWF(filter)->rfilter = rval;
2482
2644
  }
2483
2645
  return filter;
2484
2646
  }
2485
2647
 
2486
2648
  static TopDocs *
2487
- frt_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
2649
+ frb_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
2488
2650
  {
2489
2651
  VALUE rval;
2490
2652
  int offset = 0, limit = 10;
@@ -2492,7 +2654,8 @@ frt_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
2492
2654
  Sort *sort = NULL;
2493
2655
  TopDocs *td;
2494
2656
 
2495
- filter_ft filter_func = NULL;
2657
+ PostFilter post_filter_holder;
2658
+ PostFilter *post_filter = NULL;
2496
2659
 
2497
2660
  if (Qnil != roptions) {
2498
2661
  if (Qnil != (rval = rb_hash_aref(roptions, sym_offset))) {
@@ -2503,32 +2666,48 @@ frt_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
2503
2666
  if (Qnil != (rval = rb_hash_aref(roptions, sym_limit))) {
2504
2667
  if (TYPE(rval) == T_FIXNUM) {
2505
2668
  limit = FIX2INT(rval);
2506
- if (limit <= 0)
2669
+ if (limit <= 0) {
2507
2670
  rb_raise(rb_eArgError, ":limit must be > 0");
2508
- } else if (rval == sym_all) {
2671
+ }
2672
+ }
2673
+ else if (rval == sym_all) {
2509
2674
  limit = INT_MAX;
2510
- } else {
2675
+ }
2676
+ else {
2511
2677
  rb_raise(rb_eArgError, "%s is not a sensible :limit value "
2512
2678
  "Please use a positive integer or :all",
2513
- rb_obj_as_string(rval));
2679
+ rs2s(rb_obj_as_string(rval)));
2514
2680
  }
2515
2681
  }
2516
2682
  if (Qnil != (rval = rb_hash_aref(roptions, sym_filter))) {
2517
- filter = frt_get_cwrapped_filter(rval);
2683
+ filter = frb_get_cwrapped_filter(rval);
2684
+ }
2685
+ if (Qnil != (rval = rb_hash_aref(roptions, sym_c_filter_proc))) {
2686
+ post_filter = DATA_PTR(rval);
2518
2687
  }
2519
2688
  if (Qnil != (rval = rb_hash_aref(roptions, sym_filter_proc))) {
2520
- filter_func = &call_filter_proc;
2521
- sea->arg = (void *)rval;
2689
+ if (rb_respond_to(rval, id_call)) {
2690
+ if (post_filter) {
2691
+ rb_raise(rb_eArgError, "Cannot pass both :filter_proc and "
2692
+ ":c_filter_proc to the same search");
2693
+ }
2694
+ post_filter_holder.filter_func = &call_filter_proc;
2695
+ post_filter_holder.arg = (void *)rval;
2696
+ post_filter = &post_filter_holder;
2697
+ }
2698
+ else {
2699
+ post_filter = DATA_PTR(rval);
2700
+ }
2522
2701
  }
2523
2702
  if (Qnil != (rval = rb_hash_aref(roptions, sym_sort))) {
2524
2703
  if (TYPE(rval) != T_DATA || CLASS_OF(rval) == cSortField) {
2525
- rval = frt_sort_init(1, &rval, frt_sort_alloc(cSort));
2704
+ rval = frb_sort_init(1, &rval, frb_sort_alloc(cSort));
2526
2705
  }
2527
2706
  Data_Get_Struct(rval, Sort, sort);
2528
2707
  }
2529
2708
  }
2530
2709
 
2531
- td = sea->search(sea, query, offset, limit, filter, sort, filter_func, 0);
2710
+ td = sea->search(sea, query, offset, limit, filter, sort, post_filter, 0);
2532
2711
  if (filter) filt_deref(filter);
2533
2712
  return td;
2534
2713
  }
@@ -2564,19 +2743,22 @@ frt_sea_search_internal(Query *query, VALUE roptions, Searcher *sea)
2564
2743
  * on this, see the documentation for SortField
2565
2744
  * :filter:: a Filter object to filter the search results with
2566
2745
  * :filter_proc:: a filter Proc is a Proc which takes the doc_id, the score
2567
- * and the Searcher object as its parameters and returns a
2568
- * Boolean value specifying whether the result should be
2569
- * included in the result set.
2746
+ * and the Searcher object as its parameters and returns
2747
+ * either a Boolean value specifying whether the result
2748
+ * should be included in the result set, or a Float between 0
2749
+ * and 1.0 to be used as a factor to scale the score of the
2750
+ * object. This can be used, for example, to weight the score
2751
+ * of a matched document by it's age.
2570
2752
  */
2571
2753
  static VALUE
2572
- frt_sea_search(int argc, VALUE *argv, VALUE self)
2754
+ frb_sea_search(int argc, VALUE *argv, VALUE self)
2573
2755
  {
2574
2756
  GET_SEA();
2575
2757
  VALUE rquery, roptions;
2576
2758
  Query *query;
2577
2759
  rb_scan_args(argc, argv, "11", &rquery, &roptions);
2578
2760
  Data_Get_Struct(rquery, Query, query);
2579
- return frt_get_td(frt_sea_search_internal(query, roptions, sea), self);
2761
+ return frb_get_td(frb_sea_search_internal(query, roptions, sea), self);
2580
2762
  }
2581
2763
 
2582
2764
  /*
@@ -2621,7 +2803,7 @@ frt_sea_search(int argc, VALUE *argv, VALUE self)
2621
2803
  * included in the result set.
2622
2804
  */
2623
2805
  static VALUE
2624
- frt_sea_search_each(int argc, VALUE *argv, VALUE self)
2806
+ frb_sea_search_each(int argc, VALUE *argv, VALUE self)
2625
2807
  {
2626
2808
  int i;
2627
2809
  Query *q;
@@ -2632,10 +2814,11 @@ frt_sea_search_each(int argc, VALUE *argv, VALUE self)
2632
2814
 
2633
2815
  rb_scan_args(argc, argv, "11", &rquery, &roptions);
2634
2816
 
2817
+ #ifndef FRT_RUBY_VERSION_1_9
2635
2818
  rb_thread_critical = Qtrue;
2636
-
2819
+ #endif
2637
2820
  Data_Get_Struct(rquery, Query, q);
2638
- td = frt_sea_search_internal(q, roptions, sea);
2821
+ td = frb_sea_search_internal(q, roptions, sea);
2639
2822
 
2640
2823
  max_score = (td->max_score > 1.0) ? td->max_score : 1.0;
2641
2824
 
@@ -2648,11 +2831,107 @@ frt_sea_search_each(int argc, VALUE *argv, VALUE self)
2648
2831
  rtotal_hits = INT2FIX(td->total_hits);
2649
2832
  td_destroy(td);
2650
2833
 
2834
+ #ifndef FRT_RUBY_VERSION_1_9
2651
2835
  rb_thread_critical = 0;
2652
-
2836
+ #endif
2653
2837
  return rtotal_hits;
2654
2838
  }
2655
2839
 
2840
+ /*
2841
+ * call-seq:
2842
+ * searcher.scan(query, options = {}) -> Array (doc_nums)
2843
+ *
2844
+ * Run a query through the Searcher on the index, ignoring scoring and
2845
+ * starting at +:start_doc+ and stopping when +:limit+ matches have been
2846
+ * found. It returns an array of the matching document numbers.
2847
+ *
2848
+ * There is a big performance advange when using this search method on a very
2849
+ * large index when there are potentially thousands of matching documents and
2850
+ * you only want say 50 of them. The other search methods need to look at
2851
+ * every single match to decide which one has the highest score. This search
2852
+ * method just needs to find +:limit+ number of matches before it returns.
2853
+ *
2854
+ * === Options
2855
+ *
2856
+ * :start_doc:: Default: 0. The start document to start the search from.
2857
+ * NOTE very carefully that this is not the same as the
2858
+ * +:offset+ parameter used in the other search methods which
2859
+ * refers to the offset in the result-set. This is the
2860
+ * document to start the scan from. So if you scanning
2861
+ * through the index in increments of 50 documents at a time
2862
+ * you need to use the last matched doc in the previous
2863
+ * search to start your next search. See the example below.
2864
+ * :limit:: Default: 50. This is the number of results you want
2865
+ * returned, also called the page size. Set +:limit+ to
2866
+ * +:all+ to return all results.
2867
+ * TODO: add option to return loaded documents instead
2868
+ *
2869
+ * === Options
2870
+ *
2871
+ * start_doc = 0
2872
+ * begin
2873
+ * results = @searcher.scan(query, :start_doc => start_doc)
2874
+ * yield results # or do something with them
2875
+ * start_doc = results.last
2876
+ * # start_doc will be nil now if results is empty, ie no more matches
2877
+ * end while start_doc
2878
+ */
2879
+ static VALUE
2880
+ frb_sea_scan(int argc, VALUE *argv, VALUE self)
2881
+ {
2882
+ Query *q;
2883
+ int i, count;
2884
+ VALUE rval, rquery, roptions;
2885
+ int *doc_array;
2886
+ VALUE rdoc_array;
2887
+ int start_doc = 0, limit = 50;
2888
+ GET_SEA();
2889
+ rb_scan_args(argc, argv, "11", &rquery, &roptions);
2890
+ Data_Get_Struct(rquery, Query, q);
2891
+
2892
+ if (Qnil != roptions) {
2893
+ Check_Type(roptions, T_HASH);
2894
+ if (Qnil != (rval = rb_hash_aref(roptions, sym_start_doc))) {
2895
+ Check_Type(rval, T_FIXNUM);
2896
+ start_doc = FIX2INT(rval);
2897
+ if (start_doc < 0) {
2898
+ rb_raise(rb_eArgError, ":start_doc must be >= 0");
2899
+ }
2900
+ }
2901
+ if (Qnil != (rval = rb_hash_aref(roptions, sym_limit))) {
2902
+ if (TYPE(rval) == T_FIXNUM) {
2903
+ limit = FIX2INT(rval);
2904
+ if (limit <= 0) {
2905
+ rb_raise(rb_eArgError, ":limit must be > 0");
2906
+ }
2907
+ }
2908
+ else if (rval == sym_all) {
2909
+ limit = INT_MAX;
2910
+ }
2911
+ else {
2912
+ rb_raise(rb_eArgError, "%s is not a sensible :limit value "
2913
+ "Please use a positive integer or :all",
2914
+ rs2s(rb_obj_as_string(rval)));
2915
+ }
2916
+ }
2917
+ }
2918
+
2919
+ #ifndef FRT_RUBY_VERSION_1_9
2920
+ rb_thread_critical = Qtrue;
2921
+ #endif
2922
+ doc_array = ALLOC_N(int, limit);
2923
+ count = searcher_search_unscored(sea, q, doc_array, limit, start_doc);
2924
+ rdoc_array = rb_ary_new2(count);
2925
+ for (i = 0; i < count; i++) {
2926
+ rb_ary_store(rdoc_array, i, INT2FIX(doc_array[i]));
2927
+ }
2928
+ free(doc_array);
2929
+ #ifndef FRT_RUBY_VERSION_1_9
2930
+ rb_thread_critical = 0;
2931
+ #endif
2932
+ return rdoc_array;
2933
+ }
2934
+
2656
2935
  /*
2657
2936
  * call-seq:
2658
2937
  * searcher.explain(query, doc_id) -> Explanation
@@ -2665,7 +2944,7 @@ frt_sea_search_each(int argc, VALUE *argv, VALUE self)
2665
2944
  * puts searcher.explain(query, doc_id).to_s
2666
2945
  */
2667
2946
  static VALUE
2668
- frt_sea_explain(VALUE self, VALUE rquery, VALUE rdoc_id)
2947
+ frb_sea_explain(VALUE self, VALUE rquery, VALUE rdoc_id)
2669
2948
  {
2670
2949
  GET_SEA();
2671
2950
  Query *query;
@@ -2698,7 +2977,7 @@ frt_sea_explain(VALUE self, VALUE rquery, VALUE rdoc_id)
2698
2977
  * want to change this so a Unicode ellipsis character.
2699
2978
  */
2700
2979
  static VALUE
2701
- frt_sea_highlight(int argc, VALUE *argv, VALUE self)
2980
+ frb_sea_highlight(int argc, VALUE *argv, VALUE self)
2702
2981
  {
2703
2982
  GET_SEA();
2704
2983
  VALUE rquery, rdoc_id, rfield, roptions, v;
@@ -2742,7 +3021,7 @@ frt_sea_highlight(int argc, VALUE *argv, VALUE self)
2742
3021
  if ((excerpts = searcher_highlight(sea,
2743
3022
  query,
2744
3023
  FIX2INT(rdoc_id),
2745
- frt_field(rfield),
3024
+ frb_field(rfield),
2746
3025
  excerpt_length,
2747
3026
  num_excerpts,
2748
3027
  pre_tag,
@@ -2753,8 +3032,7 @@ frt_sea_highlight(int argc, VALUE *argv, VALUE self)
2753
3032
  VALUE rexcerpts = rb_ary_new2(size);
2754
3033
 
2755
3034
  for (i = 0; i < size; i++) {
2756
- RARRAY(rexcerpts)->ptr[i] = rb_str_new2(excerpts[i]);
2757
- RARRAY(rexcerpts)->len++;
3035
+ rb_ary_store(rexcerpts, i, rb_str_new2(excerpts[i]));
2758
3036
  }
2759
3037
  ary_destroy(excerpts, &free);
2760
3038
  return rexcerpts;
@@ -2769,15 +3047,15 @@ frt_sea_highlight(int argc, VALUE *argv, VALUE self)
2769
3047
  ****************************************************************************/
2770
3048
 
2771
3049
  static void
2772
- frt_sea_mark(void *p)
3050
+ frb_sea_mark(void *p)
2773
3051
  {
2774
3052
  IndexSearcher *isea = (IndexSearcher *)p;
2775
- frt_gc_mark(isea->ir);
2776
- frt_gc_mark(isea->ir->store);
3053
+ frb_gc_mark(isea->ir);
3054
+ frb_gc_mark(isea->ir->store);
2777
3055
  }
2778
3056
 
2779
3057
  #define FRT_GET_IR(rir, ir) do {\
2780
- rir = Data_Wrap_Struct(cIndexReader, &frt_ir_mark, &frt_ir_free, ir);\
3058
+ rir = Data_Wrap_Struct(cIndexReader, &frb_ir_mark, &frb_ir_free, ir);\
2781
3059
  object_add(ir, rir);\
2782
3060
  } while (0)
2783
3061
 
@@ -2792,13 +3070,13 @@ frt_sea_mark(void *p)
2792
3070
  * directories.
2793
3071
  */
2794
3072
  static VALUE
2795
- frt_sea_init(VALUE self, VALUE obj)
3073
+ frb_sea_init(VALUE self, VALUE obj)
2796
3074
  {
2797
3075
  Store *store = NULL;
2798
3076
  IndexReader *ir = NULL;
2799
3077
  Searcher *sea;
2800
3078
  if (TYPE(obj) == T_STRING) {
2801
- frt_create_dir(obj);
3079
+ frb_create_dir(obj);
2802
3080
  store = open_fs_store(StringValueCStr(obj));
2803
3081
  ir = ir_open(store);
2804
3082
  DEREF(store);
@@ -2818,7 +3096,7 @@ frt_sea_init(VALUE self, VALUE obj)
2818
3096
 
2819
3097
  sea = isea_new(ir);
2820
3098
  ((IndexSearcher *)sea)->close_ir = false;
2821
- Frt_Wrap_Struct(self, &frt_sea_mark, &frt_sea_free, sea);
3099
+ Frt_Wrap_Struct(self, &frb_sea_mark, &frb_sea_free, sea);
2822
3100
  object_add(sea, self);
2823
3101
 
2824
3102
  return self;
@@ -2831,7 +3109,7 @@ frt_sea_init(VALUE self, VALUE obj)
2831
3109
  ****************************************************************************/
2832
3110
 
2833
3111
  static void
2834
- frt_ms_free(void *p)
3112
+ frb_ms_free(void *p)
2835
3113
  {
2836
3114
  Searcher *sea = (Searcher *)p;
2837
3115
  MultiSearcher *msea = (MultiSearcher *)sea;
@@ -2841,12 +3119,12 @@ frt_ms_free(void *p)
2841
3119
  }
2842
3120
 
2843
3121
  static void
2844
- frt_ms_mark(void *p)
3122
+ frb_ms_mark(void *p)
2845
3123
  {
2846
3124
  int i;
2847
3125
  MultiSearcher *msea = (MultiSearcher *)p;
2848
3126
  for (i = 0; i < msea->s_cnt; i++) {
2849
- frt_gc_mark(msea->searchers[i]);
3127
+ frb_gc_mark(msea->searchers[i]);
2850
3128
  }
2851
3129
  }
2852
3130
 
@@ -2858,7 +3136,7 @@ frt_ms_mark(void *p)
2858
3136
  * constructor.
2859
3137
  */
2860
3138
  static VALUE
2861
- frt_ms_init(int argc, VALUE *argv, VALUE self)
3139
+ frb_ms_init(int argc, VALUE *argv, VALUE self)
2862
3140
  {
2863
3141
  int i, j, top = 0, capa = argc;
2864
3142
 
@@ -2870,10 +3148,10 @@ frt_ms_init(int argc, VALUE *argv, VALUE self)
2870
3148
  rsearcher = argv[i];
2871
3149
  switch (TYPE(rsearcher)) {
2872
3150
  case T_ARRAY:
2873
- capa += RARRAY(rsearcher)->len;
3151
+ capa += RARRAY_LEN(rsearcher);
2874
3152
  REALLOC_N(searchers, Searcher *, capa);
2875
- for (j = 0; j < RARRAY(rsearcher)->len; j++) {
2876
- VALUE rs = RARRAY(rsearcher)->ptr[j];
3153
+ for (j = 0; j < RARRAY_LEN(rsearcher); j++) {
3154
+ VALUE rs = RARRAY_PTR(rsearcher)[j];
2877
3155
  Data_Get_Struct(rs, Searcher, s);
2878
3156
  searchers[top++] = s;
2879
3157
  }
@@ -2889,7 +3167,7 @@ frt_ms_init(int argc, VALUE *argv, VALUE self)
2889
3167
  }
2890
3168
  }
2891
3169
  s = msea_new(searchers, top, false);
2892
- Frt_Wrap_Struct(self, &frt_ms_mark, &frt_ms_free, s);
3170
+ Frt_Wrap_Struct(self, &frb_ms_mark, &frb_ms_free, s);
2893
3171
  object_add(s, self);
2894
3172
  return self;
2895
3173
  }
@@ -2962,8 +3240,8 @@ Init_TopDocs(void)
2962
3240
  NULL);
2963
3241
  rb_set_class_path(cTopDocs, mSearch, td_class);
2964
3242
  rb_const_set(mSearch, rb_intern(td_class), cTopDocs);
2965
- rb_define_method(cTopDocs, "to_s", frt_td_to_s, -1);
2966
- rb_define_method(cTopDocs, "to_json", frt_td_to_json, 0);
3243
+ rb_define_method(cTopDocs, "to_s", frb_td_to_s, -1);
3244
+ rb_define_method(cTopDocs, "to_json", frb_td_to_json, 0);
2967
3245
  id_hits = rb_intern("hits");
2968
3246
  id_total_hits = rb_intern("total_hits");
2969
3247
  id_max_score = rb_intern("max_score");
@@ -2990,11 +3268,11 @@ static void
2990
3268
  Init_Explanation(void)
2991
3269
  {
2992
3270
  cExplanation = rb_define_class_under(mSearch, "Explanation", rb_cObject);
2993
- rb_define_alloc_func(cExplanation, frt_data_alloc);
3271
+ rb_define_alloc_func(cExplanation, frb_data_alloc);
2994
3272
 
2995
- rb_define_method(cExplanation, "to_s", frt_expl_to_s, 0);
2996
- rb_define_method(cExplanation, "to_html", frt_expl_to_html, 0);
2997
- rb_define_method(cExplanation, "score", frt_expl_score, 0);
3273
+ rb_define_method(cExplanation, "to_s", frb_expl_to_s, 0);
3274
+ rb_define_method(cExplanation, "to_html", frb_expl_to_html, 0);
3275
+ rb_define_method(cExplanation, "score", frb_expl_score, 0);
2998
3276
  }
2999
3277
 
3000
3278
  /*
@@ -3038,13 +3316,13 @@ Init_Query(void)
3038
3316
  {
3039
3317
  cQuery = rb_define_class_under(mSearch, "Query", rb_cObject);
3040
3318
 
3041
- rb_define_method(cQuery, "to_s", frt_q_to_s, -1);
3042
- rb_define_method(cQuery, "boost", frt_q_get_boost, 0);
3043
- rb_define_method(cQuery, "boost=", frt_q_set_boost, 1);
3044
- rb_define_method(cQuery, "eql?", frt_q_eql, 1);
3045
- rb_define_method(cQuery, "==", frt_q_eql, 1);
3046
- rb_define_method(cQuery, "hash", frt_q_hash, 0);
3047
- rb_define_method(cQuery, "terms", frt_q_get_terms, 1);
3319
+ rb_define_method(cQuery, "to_s", frb_q_to_s, -1);
3320
+ rb_define_method(cQuery, "boost", frb_q_get_boost, 0);
3321
+ rb_define_method(cQuery, "boost=", frb_q_set_boost, 1);
3322
+ rb_define_method(cQuery, "eql?", frb_q_eql, 1);
3323
+ rb_define_method(cQuery, "==", frb_q_eql, 1);
3324
+ rb_define_method(cQuery, "hash", frb_q_hash, 0);
3325
+ rb_define_method(cQuery, "terms", frb_q_get_terms, 1);
3048
3326
  }
3049
3327
 
3050
3328
  /*
@@ -3071,9 +3349,9 @@ static void
3071
3349
  Init_TermQuery(void)
3072
3350
  {
3073
3351
  cTermQuery = rb_define_class_under(mSearch, "TermQuery", cQuery);
3074
- rb_define_alloc_func(cTermQuery, frt_data_alloc);
3352
+ rb_define_alloc_func(cTermQuery, frb_data_alloc);
3075
3353
 
3076
- rb_define_method(cTermQuery, "initialize", frt_tq_init, 2);
3354
+ rb_define_method(cTermQuery, "initialize", frb_tq_init, 2);
3077
3355
  }
3078
3356
 
3079
3357
  /*
@@ -3105,17 +3383,20 @@ Init_MultiTermQuery(void)
3105
3383
  sym_min_score = ID2SYM(rb_intern("min_score"));
3106
3384
 
3107
3385
  cMultiTermQuery = rb_define_class_under(mSearch, "MultiTermQuery", cQuery);
3108
- rb_define_alloc_func(cMultiTermQuery, frt_data_alloc);
3109
-
3386
+ rb_define_alloc_func(cMultiTermQuery, frb_data_alloc);
3387
+ #ifdef FRT_RUBY_VERSION_1_9
3388
+ rb_cvar_set(cMultiTermQuery, id_default_max_terms, INT2FIX(512));
3389
+ #else
3110
3390
  rb_cvar_set(cMultiTermQuery, id_default_max_terms, INT2FIX(512), Qfalse);
3391
+ #endif
3111
3392
  rb_define_singleton_method(cMultiTermQuery, "default_max_terms",
3112
- frt_mtq_get_dmt, 0);
3393
+ frb_mtq_get_dmt, 0);
3113
3394
  rb_define_singleton_method(cMultiTermQuery, "default_max_terms=",
3114
- frt_mtq_set_dmt, 1);
3395
+ frb_mtq_set_dmt, 1);
3115
3396
 
3116
- rb_define_method(cMultiTermQuery, "initialize", frt_mtq_init, -1);
3117
- rb_define_method(cMultiTermQuery, "add_term", frt_mtq_add_term, -1);
3118
- rb_define_method(cMultiTermQuery, "<<", frt_mtq_add_term, -1);
3397
+ rb_define_method(cMultiTermQuery, "initialize", frb_mtq_init, -1);
3398
+ rb_define_method(cMultiTermQuery, "add_term", frb_mtq_add_term, -1);
3399
+ rb_define_method(cMultiTermQuery, "<<", frb_mtq_add_term, -1);
3119
3400
  }
3120
3401
 
3121
3402
  static void Init_BooleanClause(void);
@@ -3149,11 +3430,11 @@ static void
3149
3430
  Init_BooleanQuery(void)
3150
3431
  {
3151
3432
  cBooleanQuery = rb_define_class_under(mSearch, "BooleanQuery", cQuery);
3152
- rb_define_alloc_func(cBooleanQuery, frt_data_alloc);
3433
+ rb_define_alloc_func(cBooleanQuery, frb_data_alloc);
3153
3434
 
3154
- rb_define_method(cBooleanQuery, "initialize", frt_bq_init, -1);
3155
- rb_define_method(cBooleanQuery, "add_query", frt_bq_add_query, -1);
3156
- rb_define_method(cBooleanQuery, "<<", frt_bq_add_query, -1);
3435
+ rb_define_method(cBooleanQuery, "initialize", frb_bq_init, -1);
3436
+ rb_define_method(cBooleanQuery, "add_query", frb_bq_add_query, -1);
3437
+ rb_define_method(cBooleanQuery, "<<", frb_bq_add_query, -1);
3157
3438
 
3158
3439
  Init_BooleanClause();
3159
3440
  }
@@ -3186,15 +3467,15 @@ Init_BooleanClause(void)
3186
3467
 
3187
3468
  cBooleanClause = rb_define_class_under(cBooleanQuery, "BooleanClause",
3188
3469
  rb_cObject);
3189
- rb_define_alloc_func(cBooleanClause, frt_data_alloc);
3470
+ rb_define_alloc_func(cBooleanClause, frb_data_alloc);
3190
3471
 
3191
- rb_define_method(cBooleanClause, "initialize", frt_bc_init, -1);
3192
- rb_define_method(cBooleanClause, "query", frt_bc_get_query, 0);
3193
- rb_define_method(cBooleanClause, "query=", frt_bc_set_query, 1);
3194
- rb_define_method(cBooleanClause, "required?", frt_bc_is_required, 0);
3195
- rb_define_method(cBooleanClause, "prohibited?", frt_bc_is_prohibited, 0);
3196
- rb_define_method(cBooleanClause, "occur=", frt_bc_set_occur, 1);
3197
- rb_define_method(cBooleanClause, "to_s", frt_bc_to_s, 0);
3472
+ rb_define_method(cBooleanClause, "initialize", frb_bc_init, -1);
3473
+ rb_define_method(cBooleanClause, "query", frb_bc_get_query, 0);
3474
+ rb_define_method(cBooleanClause, "query=", frb_bc_set_query, 1);
3475
+ rb_define_method(cBooleanClause, "required?", frb_bc_is_required, 0);
3476
+ rb_define_method(cBooleanClause, "prohibited?", frb_bc_is_prohibited, 0);
3477
+ rb_define_method(cBooleanClause, "occur=", frb_bc_set_occur, 1);
3478
+ rb_define_method(cBooleanClause, "to_s", frb_bc_to_s, 0);
3198
3479
  }
3199
3480
 
3200
3481
  /*
@@ -3212,6 +3493,26 @@ Init_BooleanClause(void)
3212
3493
  * 2006 inclusive you would write the query like this;
3213
3494
  *
3214
3495
  * query = RangeQuery.new(:create_date, :>= "20060101", :<= "20060126")
3496
+ *
3497
+ * == Range queries on numbers
3498
+ *
3499
+ * There is now a new query called TypedRangeQuery which detects the type of
3500
+ * the range and if the range is numerical it will find a numerical range.
3501
+ * This allows you to do range queries with negative numbers and without
3502
+ * having to pad the field. However, RangeQuery will perform a lot faster on
3503
+ * large indexes so if you are working with a very large index you will need
3504
+ * to normalize your number fields so that they are a fixed width and always
3505
+ * positive. That way the standard String range query will do fine.
3506
+ *
3507
+ * For example, if you have the numbers;
3508
+ *
3509
+ * [10, -999, -90, 100, 534]
3510
+ *
3511
+ * Then the can be normalized to;
3512
+ *
3513
+ * # note that we have added 1000 to all numbers to make them all positive
3514
+ * [1010, 0001, 0910, 1100, 1534]
3515
+ *
3215
3516
  */
3216
3517
  static void
3217
3518
  Init_RangeQuery(void)
@@ -3229,9 +3530,44 @@ Init_RangeQuery(void)
3229
3530
  sym_greater_than_or_equal_to = ID2SYM(rb_intern(">="));
3230
3531
 
3231
3532
  cRangeQuery = rb_define_class_under(mSearch, "RangeQuery", cQuery);
3232
- rb_define_alloc_func(cRangeQuery, frt_data_alloc);
3533
+ rb_define_alloc_func(cRangeQuery, frb_data_alloc);
3534
+
3535
+ rb_define_method(cRangeQuery, "initialize", frb_rq_init, 2);
3536
+ }
3537
+
3538
+ /*
3539
+ * Document-class: Ferret::Search::TypedRangeQuery
3540
+ *
3541
+ * == Summary
3542
+ *
3543
+ * TypedRangeQuery is used to find documents with terms in a range.
3544
+ * RangeQuerys are usually used on untokenized fields like date fields or
3545
+ * number fields. TypedRangeQuery is particularly useful for fields with
3546
+ * unnormalized numbers, both positive and negative, integer and float.
3547
+ *
3548
+ * == Example
3549
+ *
3550
+ * To find all documents written between January 1st 2006 and January 26th
3551
+ * 2006 inclusive you would write the query like this;
3552
+ *
3553
+ * query = RangeQuery.new(:create_date, :>= "-1.0", :<= "10.0")
3554
+ *
3555
+ * == Performance Note
3556
+ *
3557
+ * TypedRangeQuery works by converting all the terms in a field to numbers
3558
+ * and then comparing those numbers with the range bondaries. This can have
3559
+ * quite an impact on performance on large indexes so in those cases it is
3560
+ * usually better to use a standard RangeQuery. This will require a little
3561
+ * work on your behalf. See RangeQuery for notes on how to do this.
3562
+ */
3563
+ static void
3564
+ Init_TypedRangeQuery(void)
3565
+ {
3566
+ cTypedRangeQuery =
3567
+ rb_define_class_under(mSearch, "TypedRangeQuery", cQuery);
3568
+ rb_define_alloc_func(cTypedRangeQuery, frb_data_alloc);
3233
3569
 
3234
- rb_define_method(cRangeQuery, "initialize", frt_rq_init, 2);
3570
+ rb_define_method(cTypedRangeQuery, "initialize", frb_trq_init, 2);
3235
3571
  }
3236
3572
 
3237
3573
  /*
@@ -3301,13 +3637,13 @@ static void
3301
3637
  Init_PhraseQuery(void)
3302
3638
  {
3303
3639
  cPhraseQuery = rb_define_class_under(mSearch, "PhraseQuery", cQuery);
3304
- rb_define_alloc_func(cPhraseQuery, frt_data_alloc);
3640
+ rb_define_alloc_func(cPhraseQuery, frb_data_alloc);
3305
3641
 
3306
- rb_define_method(cPhraseQuery, "initialize", frt_phq_init, -1);
3307
- rb_define_method(cPhraseQuery, "add_term", frt_phq_add, -1);
3308
- rb_define_method(cPhraseQuery, "<<", frt_phq_add, -1);
3309
- rb_define_method(cPhraseQuery, "slop", frt_phq_get_slop, 0);
3310
- rb_define_method(cPhraseQuery, "slop=", frt_phq_set_slop, 1);
3642
+ rb_define_method(cPhraseQuery, "initialize", frb_phq_init, -1);
3643
+ rb_define_method(cPhraseQuery, "add_term", frb_phq_add, -1);
3644
+ rb_define_method(cPhraseQuery, "<<", frb_phq_add, -1);
3645
+ rb_define_method(cPhraseQuery, "slop", frb_phq_get_slop, 0);
3646
+ rb_define_method(cPhraseQuery, "slop=", frb_phq_set_slop, 1);
3311
3647
  }
3312
3648
 
3313
3649
  /*
@@ -3343,9 +3679,9 @@ static void
3343
3679
  Init_PrefixQuery(void)
3344
3680
  {
3345
3681
  cPrefixQuery = rb_define_class_under(mSearch, "PrefixQuery", cQuery);
3346
- rb_define_alloc_func(cPrefixQuery, frt_data_alloc);
3682
+ rb_define_alloc_func(cPrefixQuery, frb_data_alloc);
3347
3683
 
3348
- rb_define_method(cPrefixQuery, "initialize", frt_prq_init, -1);
3684
+ rb_define_method(cPrefixQuery, "initialize", frb_prq_init, -1);
3349
3685
  }
3350
3686
 
3351
3687
  /*
@@ -3378,9 +3714,9 @@ static void
3378
3714
  Init_WildcardQuery(void)
3379
3715
  {
3380
3716
  cWildcardQuery = rb_define_class_under(mSearch, "WildcardQuery", cQuery);
3381
- rb_define_alloc_func(cWildcardQuery, frt_data_alloc);
3717
+ rb_define_alloc_func(cWildcardQuery, frb_data_alloc);
3382
3718
 
3383
- rb_define_method(cWildcardQuery, "initialize", frt_wcq_init, -1);
3719
+ rb_define_method(cWildcardQuery, "initialize", frb_wcq_init, -1);
3384
3720
  }
3385
3721
 
3386
3722
  /*
@@ -3414,24 +3750,31 @@ Init_FuzzyQuery(void)
3414
3750
  sym_prefix_length = ID2SYM(rb_intern("prefix_length"));
3415
3751
 
3416
3752
  cFuzzyQuery = rb_define_class_under(mSearch, "FuzzyQuery", cQuery);
3417
- rb_define_alloc_func(cFuzzyQuery, frt_data_alloc);
3753
+ rb_define_alloc_func(cFuzzyQuery, frb_data_alloc);
3754
+ #ifdef FRT_RUBY_VERSION_1_9
3755
+ rb_cvar_set(cFuzzyQuery, id_default_min_similarity,
3756
+ rb_float_new(0.5));
3757
+ rb_cvar_set(cFuzzyQuery, id_default_prefix_length,
3758
+ INT2FIX(0));
3759
+ #else
3418
3760
  rb_cvar_set(cFuzzyQuery, id_default_min_similarity,
3419
3761
  rb_float_new(0.5), Qfalse);
3420
3762
  rb_cvar_set(cFuzzyQuery, id_default_prefix_length,
3421
3763
  INT2FIX(0), Qfalse);
3764
+ #endif
3422
3765
 
3423
3766
  rb_define_singleton_method(cFuzzyQuery, "default_min_similarity",
3424
- frt_fq_get_dms, 0);
3767
+ frb_fq_get_dms, 0);
3425
3768
  rb_define_singleton_method(cFuzzyQuery, "default_min_similarity=",
3426
- frt_fq_set_dms, 1);
3769
+ frb_fq_set_dms, 1);
3427
3770
  rb_define_singleton_method(cFuzzyQuery, "default_prefix_length",
3428
- frt_fq_get_dpl, 0);
3771
+ frb_fq_get_dpl, 0);
3429
3772
  rb_define_singleton_method(cFuzzyQuery, "default_prefix_length=",
3430
- frt_fq_set_dpl, 1);
3773
+ frb_fq_set_dpl, 1);
3431
3774
 
3432
- rb_define_method(cFuzzyQuery, "initialize", frt_fq_init, -1);
3433
- rb_define_method(cFuzzyQuery, "prefix_length", frt_fq_pre_len, 0);
3434
- rb_define_method(cFuzzyQuery, "min_similarity", frt_fq_min_sim, 0);
3775
+ rb_define_method(cFuzzyQuery, "initialize", frb_fq_init, -1);
3776
+ rb_define_method(cFuzzyQuery, "prefix_length", frb_fq_pre_len, 0);
3777
+ rb_define_method(cFuzzyQuery, "min_similarity", frb_fq_min_sim, 0);
3435
3778
  }
3436
3779
 
3437
3780
  /*
@@ -3447,9 +3790,9 @@ static void
3447
3790
  Init_MatchAllQuery(void)
3448
3791
  {
3449
3792
  cMatchAllQuery = rb_define_class_under(mSearch, "MatchAllQuery", cQuery);
3450
- rb_define_alloc_func(cMatchAllQuery, frt_maq_alloc);
3793
+ rb_define_alloc_func(cMatchAllQuery, frb_maq_alloc);
3451
3794
 
3452
- rb_define_method(cMatchAllQuery, "initialize", frt_maq_init, 0);
3795
+ rb_define_method(cMatchAllQuery, "initialize", frb_maq_init, 0);
3453
3796
  }
3454
3797
 
3455
3798
  /*
@@ -3477,9 +3820,9 @@ Init_ConstantScoreQuery(void)
3477
3820
  {
3478
3821
  cConstantScoreQuery = rb_define_class_under(mSearch,
3479
3822
  "ConstantScoreQuery", cQuery);
3480
- rb_define_alloc_func(cConstantScoreQuery, frt_data_alloc);
3823
+ rb_define_alloc_func(cConstantScoreQuery, frb_data_alloc);
3481
3824
 
3482
- rb_define_method(cConstantScoreQuery, "initialize", frt_csq_init, 1);
3825
+ rb_define_method(cConstantScoreQuery, "initialize", frb_csq_init, 1);
3483
3826
  }
3484
3827
 
3485
3828
  /*
@@ -3497,9 +3840,9 @@ static void
3497
3840
  Init_FilteredQuery(void)
3498
3841
  {
3499
3842
  cFilteredQuery = rb_define_class_under(mSearch, "FilteredQuery", cQuery);
3500
- rb_define_alloc_func(cFilteredQuery, frt_data_alloc);
3843
+ rb_define_alloc_func(cFilteredQuery, frb_data_alloc);
3501
3844
 
3502
- rb_define_method(cFilteredQuery, "initialize", frt_fqq_init, 2);
3845
+ rb_define_method(cFilteredQuery, "initialize", frb_fqq_init, 2);
3503
3846
  }
3504
3847
 
3505
3848
  /*
@@ -3515,9 +3858,9 @@ static void
3515
3858
  Init_SpanTermQuery(void)
3516
3859
  {
3517
3860
  cSpanTermQuery = rb_define_class_under(mSpans, "SpanTermQuery", cQuery);
3518
- rb_define_alloc_func(cSpanTermQuery, frt_data_alloc);
3861
+ rb_define_alloc_func(cSpanTermQuery, frb_data_alloc);
3519
3862
 
3520
- rb_define_method(cSpanTermQuery, "initialize", frt_spantq_init, 2);
3863
+ rb_define_method(cSpanTermQuery, "initialize", frb_spantq_init, 2);
3521
3864
  }
3522
3865
 
3523
3866
  /*
@@ -3533,9 +3876,9 @@ static void
3533
3876
  Init_SpanMultiTermQuery(void)
3534
3877
  {
3535
3878
  cSpanMultiTermQuery = rb_define_class_under(mSpans, "SpanMultiTermQuery", cQuery);
3536
- rb_define_alloc_func(cSpanMultiTermQuery, frt_data_alloc);
3879
+ rb_define_alloc_func(cSpanMultiTermQuery, frb_data_alloc);
3537
3880
 
3538
- rb_define_method(cSpanMultiTermQuery, "initialize", frt_spanmtq_init, 2);
3881
+ rb_define_method(cSpanMultiTermQuery, "initialize", frb_spanmtq_init, 2);
3539
3882
  }
3540
3883
 
3541
3884
  /*
@@ -3551,9 +3894,9 @@ static void
3551
3894
  Init_SpanPrefixQuery(void)
3552
3895
  {
3553
3896
  cSpanPrefixQuery = rb_define_class_under(mSpans, "SpanPrefixQuery", cQuery);
3554
- rb_define_alloc_func(cSpanPrefixQuery, frt_data_alloc);
3897
+ rb_define_alloc_func(cSpanPrefixQuery, frb_data_alloc);
3555
3898
 
3556
- rb_define_method(cSpanPrefixQuery, "initialize", frt_spanprq_init, -1);
3899
+ rb_define_method(cSpanPrefixQuery, "initialize", frb_spanprq_init, -1);
3557
3900
  }
3558
3901
 
3559
3902
  /*
@@ -3580,9 +3923,9 @@ static void
3580
3923
  Init_SpanFirstQuery(void)
3581
3924
  {
3582
3925
  cSpanFirstQuery = rb_define_class_under(mSpans, "SpanFirstQuery", cQuery);
3583
- rb_define_alloc_func(cSpanFirstQuery, frt_data_alloc);
3926
+ rb_define_alloc_func(cSpanFirstQuery, frb_data_alloc);
3584
3927
 
3585
- rb_define_method(cSpanFirstQuery, "initialize", frt_spanfq_init, 2);
3928
+ rb_define_method(cSpanFirstQuery, "initialize", frb_spanfq_init, 2);
3586
3929
  }
3587
3930
 
3588
3931
  /*
@@ -3631,11 +3974,11 @@ Init_SpanNearQuery(void)
3631
3974
  sym_clauses = ID2SYM(rb_intern("clauses"));
3632
3975
 
3633
3976
  cSpanNearQuery = rb_define_class_under(mSpans, "SpanNearQuery", cQuery);
3634
- rb_define_alloc_func(cSpanNearQuery, frt_data_alloc);
3977
+ rb_define_alloc_func(cSpanNearQuery, frb_data_alloc);
3635
3978
 
3636
- rb_define_method(cSpanNearQuery, "initialize", frt_spannq_init, -1);
3637
- rb_define_method(cSpanNearQuery, "add", frt_spannq_add, 1);
3638
- rb_define_method(cSpanNearQuery, "<<", frt_spannq_add, 1);
3979
+ rb_define_method(cSpanNearQuery, "initialize", frb_spannq_init, -1);
3980
+ rb_define_method(cSpanNearQuery, "add", frb_spannq_add, 1);
3981
+ rb_define_method(cSpanNearQuery, "<<", frb_spannq_add, 1);
3639
3982
  }
3640
3983
 
3641
3984
  /*
@@ -3681,11 +4024,11 @@ static void
3681
4024
  Init_SpanOrQuery(void)
3682
4025
  {
3683
4026
  cSpanOrQuery = rb_define_class_under(mSpans, "SpanOrQuery", cQuery);
3684
- rb_define_alloc_func(cSpanOrQuery, frt_data_alloc);
4027
+ rb_define_alloc_func(cSpanOrQuery, frb_data_alloc);
3685
4028
 
3686
- rb_define_method(cSpanOrQuery, "initialize", frt_spanoq_init, -1);
3687
- rb_define_method(cSpanOrQuery, "add", frt_spanoq_add, 1);
3688
- rb_define_method(cSpanOrQuery, "<<", frt_spanoq_add, 1);
4029
+ rb_define_method(cSpanOrQuery, "initialize", frb_spanoq_init, -1);
4030
+ rb_define_method(cSpanOrQuery, "add", frb_spanoq_add, 1);
4031
+ rb_define_method(cSpanOrQuery, "<<", frb_spanoq_add, 1);
3689
4032
  }
3690
4033
 
3691
4034
  /*
@@ -3715,9 +4058,9 @@ static void
3715
4058
  Init_SpanNotQuery(void)
3716
4059
  {
3717
4060
  cSpanNotQuery = rb_define_class_under(mSpans, "SpanNotQuery", cQuery);
3718
- rb_define_alloc_func(cSpanNotQuery, frt_data_alloc);
4061
+ rb_define_alloc_func(cSpanNotQuery, frb_data_alloc);
3719
4062
 
3720
- rb_define_method(cSpanNotQuery, "initialize", frt_spanxq_init, 2);
4063
+ rb_define_method(cSpanNotQuery, "initialize", frb_spanxq_init, 2);
3721
4064
  }
3722
4065
 
3723
4066
  /* rdoc hack
@@ -3762,15 +4105,48 @@ Init_Spans(void)
3762
4105
  * Find all documents created before 5th of September 2002.
3763
4106
  *
3764
4107
  * filter = RangeFilter.new(:created_on, :< => "20020905")
4108
+ *
4109
+ * == Number fields
4110
+ *
4111
+ * See RangeQuery for notes on how to use the RangeFilter on a field
4112
+ * containing numbers.
3765
4113
  */
3766
4114
  static void
3767
4115
  Init_RangeFilter(void)
3768
4116
  {
3769
4117
  cRangeFilter = rb_define_class_under(mSearch, "RangeFilter", cFilter);
3770
- frt_mark_cclass(cRangeFilter);
3771
- rb_define_alloc_func(cRangeFilter, frt_data_alloc);
4118
+ frb_mark_cclass(cRangeFilter);
4119
+ rb_define_alloc_func(cRangeFilter, frb_data_alloc);
4120
+
4121
+ rb_define_method(cRangeFilter, "initialize", frb_rf_init, 2);
4122
+ }
4123
+
4124
+ /*
4125
+ * Document-class: Ferret::Search::TypedRangeFilter
4126
+ *
4127
+ * == Summary
4128
+ *
4129
+ * TypedRangeFilter filters a set of documents which contain a
4130
+ * lexicographical range of terms (ie "aaa", "aab", "aac", etc), unless the
4131
+ * range boundaries happen to be numbers (positive, negative, integer,
4132
+ * float), in which case a numerical filter is applied. See also
4133
+ * TypedRangeQuery
4134
+ *
4135
+ * == Example
4136
+ *
4137
+ * Find all products that cost less than or equal to $50.00.
4138
+ *
4139
+ * filter = TypedRangeFilter.new(:created_on, :<= => "50.00")
4140
+ */
4141
+ static void
4142
+ Init_TypedRangeFilter(void)
4143
+ {
4144
+ cTypedRangeFilter =
4145
+ rb_define_class_under(mSearch, "TypedRangeFilter", cFilter);
4146
+ frb_mark_cclass(cTypedRangeFilter);
4147
+ rb_define_alloc_func(cTypedRangeFilter, frb_data_alloc);
3772
4148
 
3773
- rb_define_method(cRangeFilter, "initialize", frt_rf_init, 2);
4149
+ rb_define_method(cTypedRangeFilter, "initialize", frb_trf_init, 2);
3774
4150
  }
3775
4151
 
3776
4152
  /*
@@ -3802,10 +4178,10 @@ static void
3802
4178
  Init_QueryFilter(void)
3803
4179
  {
3804
4180
  cQueryFilter = rb_define_class_under(mSearch, "QueryFilter", cFilter);
3805
- frt_mark_cclass(cQueryFilter);
3806
- rb_define_alloc_func(cQueryFilter, frt_data_alloc);
4181
+ frb_mark_cclass(cQueryFilter);
4182
+ rb_define_alloc_func(cQueryFilter, frb_data_alloc);
3807
4183
 
3808
- rb_define_method(cQueryFilter, "initialize", frt_qf_init, 1);
4184
+ rb_define_method(cQueryFilter, "initialize", frb_qf_init, 1);
3809
4185
  }
3810
4186
 
3811
4187
  /*
@@ -3828,11 +4204,11 @@ Init_Filter(void)
3828
4204
  {
3829
4205
  id_bits = rb_intern("bits");
3830
4206
  cFilter = rb_define_class_under(mSearch, "Filter", rb_cObject);
3831
- frt_mark_cclass(cFilter);
3832
- rb_define_alloc_func(cConstantScoreQuery, frt_data_alloc);
4207
+ frb_mark_cclass(cFilter);
4208
+ rb_define_alloc_func(cConstantScoreQuery, frb_data_alloc);
3833
4209
 
3834
- rb_define_method(cFilter, "bits", frt_f_get_bits, 1);
3835
- rb_define_method(cFilter, "to_s", frt_f_to_s, 0);
4210
+ rb_define_method(cFilter, "bits", frb_f_get_bits, 1);
4211
+ rb_define_method(cFilter, "to_s", frb_f_to_s, 0);
3836
4212
  }
3837
4213
 
3838
4214
  /*
@@ -3890,32 +4266,32 @@ Init_SortField(void)
3890
4266
  sym_byte = ID2SYM(rb_intern("byte"));
3891
4267
 
3892
4268
  cSortField = rb_define_class_under(mSearch, "SortField", rb_cObject);
3893
- rb_define_alloc_func(cSortField, frt_data_alloc);
4269
+ rb_define_alloc_func(cSortField, frb_data_alloc);
3894
4270
 
3895
- rb_define_method(cSortField, "initialize", frt_sf_init, -1);
3896
- rb_define_method(cSortField, "reverse?", frt_sf_is_reverse, 0);
3897
- rb_define_method(cSortField, "name", frt_sf_get_name, 0);
3898
- rb_define_method(cSortField, "type", frt_sf_get_type, 0);
3899
- rb_define_method(cSortField, "comparator", frt_sf_get_comparator, 0);
3900
- rb_define_method(cSortField, "to_s", frt_sf_to_s, 0);
4271
+ rb_define_method(cSortField, "initialize", frb_sf_init, -1);
4272
+ rb_define_method(cSortField, "reverse?", frb_sf_is_reverse, 0);
4273
+ rb_define_method(cSortField, "name", frb_sf_get_name, 0);
4274
+ rb_define_method(cSortField, "type", frb_sf_get_type, 0);
4275
+ rb_define_method(cSortField, "comparator", frb_sf_get_comparator, 0);
4276
+ rb_define_method(cSortField, "to_s", frb_sf_to_s, 0);
3901
4277
 
3902
4278
  rb_define_const(cSortField, "SCORE",
3903
4279
  Data_Wrap_Struct(cSortField, NULL,
3904
- &frt_deref_free,
4280
+ &frb_deref_free,
3905
4281
  (SortField *)&SORT_FIELD_SCORE));
3906
4282
  object_add((SortField *)&SORT_FIELD_SCORE,
3907
4283
  rb_const_get(cSortField, rb_intern("SCORE")));
3908
4284
 
3909
4285
  rb_define_const(cSortField, "SCORE_REV",
3910
4286
  Data_Wrap_Struct(cSortField, NULL,
3911
- &frt_deref_free,
4287
+ &frb_deref_free,
3912
4288
  (SortField *)&SORT_FIELD_SCORE_REV));
3913
4289
  object_add((SortField *)&SORT_FIELD_SCORE_REV,
3914
4290
  rb_const_get(cSortField, rb_intern("SCORE_REV")));
3915
4291
 
3916
4292
  rb_define_const(cSortField, "DOC_ID",
3917
4293
  Data_Wrap_Struct(cSortField, NULL,
3918
- &frt_deref_free,
4294
+ &frb_deref_free,
3919
4295
  (SortField *)&SORT_FIELD_DOC));
3920
4296
 
3921
4297
  oSORT_FIELD_DOC = rb_const_get(cSortField, rb_intern("DOC_ID"));
@@ -3923,7 +4299,7 @@ Init_SortField(void)
3923
4299
 
3924
4300
  rb_define_const(cSortField, "DOC_ID_REV",
3925
4301
  Data_Wrap_Struct(cSortField, NULL,
3926
- &frt_deref_free,
4302
+ &frb_deref_free,
3927
4303
  (SortField *)&SORT_FIELD_DOC_REV));
3928
4304
  object_add((SortField *)&SORT_FIELD_DOC_REV,
3929
4305
  rb_const_get(cSortField, rb_intern("DOC_ID_REV")));
@@ -3954,16 +4330,16 @@ Init_Sort(void)
3954
4330
  {
3955
4331
  /* Sort */
3956
4332
  cSort = rb_define_class_under(mSearch, "Sort", rb_cObject);
3957
- rb_define_alloc_func(cSort, frt_sort_alloc);
4333
+ rb_define_alloc_func(cSort, frb_sort_alloc);
3958
4334
 
3959
- rb_define_method(cSort, "initialize", frt_sort_init, -1);
3960
- rb_define_method(cSort, "fields", frt_sort_get_fields, 0);
3961
- rb_define_method(cSort, "to_s", frt_sort_to_s, 0);
4335
+ rb_define_method(cSort, "initialize", frb_sort_init, -1);
4336
+ rb_define_method(cSort, "fields", frb_sort_get_fields, 0);
4337
+ rb_define_method(cSort, "to_s", frb_sort_to_s, 0);
3962
4338
 
3963
4339
  rb_define_const(cSort, "RELEVANCE",
3964
- frt_sort_init(0, NULL, frt_sort_alloc(cSort)));
4340
+ frb_sort_init(0, NULL, frb_sort_alloc(cSort)));
3965
4341
  rb_define_const(cSort, "INDEX_ORDER",
3966
- frt_sort_init(1, &oSORT_FIELD_DOC, frt_sort_alloc(cSort)));
4342
+ frb_sort_init(1, &oSORT_FIELD_DOC, frb_sort_alloc(cSort)));
3967
4343
  }
3968
4344
 
3969
4345
  /*
@@ -4000,12 +4376,14 @@ static void
4000
4376
  Init_Searcher(void)
4001
4377
  {
4002
4378
  /* option hash keys for Searcher#search */
4003
- sym_offset = ID2SYM(rb_intern("offset"));
4004
- sym_limit = ID2SYM(rb_intern("limit"));
4005
- sym_all = ID2SYM(rb_intern("all"));
4006
- sym_filter = ID2SYM(rb_intern("filter"));
4007
- sym_filter_proc = ID2SYM(rb_intern("filter_proc"));
4008
- sym_sort = ID2SYM(rb_intern("sort"));
4379
+ sym_offset = ID2SYM(rb_intern("offset"));
4380
+ sym_limit = ID2SYM(rb_intern("limit"));
4381
+ sym_start_doc = ID2SYM(rb_intern("start_doc"));
4382
+ sym_all = ID2SYM(rb_intern("all"));
4383
+ sym_filter = ID2SYM(rb_intern("filter"));
4384
+ sym_filter_proc = ID2SYM(rb_intern("filter_proc"));
4385
+ sym_c_filter_proc = ID2SYM(rb_intern("c_filter_proc"));
4386
+ sym_sort = ID2SYM(rb_intern("sort"));
4009
4387
 
4010
4388
  sym_excerpt_length = ID2SYM(rb_intern("excerpt_length"));
4011
4389
  sym_num_excerpts = ID2SYM(rb_intern("num_excerpts"));
@@ -4015,19 +4393,20 @@ Init_Searcher(void)
4015
4393
 
4016
4394
  /* Searcher */
4017
4395
  cSearcher = rb_define_class_under(mSearch, "Searcher", rb_cObject);
4018
- rb_define_alloc_func(cSearcher, frt_data_alloc);
4019
-
4020
- rb_define_method(cSearcher, "initialize", frt_sea_init, 1);
4021
- rb_define_method(cSearcher, "close", frt_sea_close, 0);
4022
- rb_define_method(cSearcher, "reader", frt_sea_get_reader, 0);
4023
- rb_define_method(cSearcher, "doc_freq", frt_sea_doc_freq, 2);
4024
- rb_define_method(cSearcher, "get_document", frt_sea_doc, 1);
4025
- rb_define_method(cSearcher, "[]", frt_sea_doc, 1);
4026
- rb_define_method(cSearcher, "max_doc", frt_sea_max_doc, 0);
4027
- rb_define_method(cSearcher, "search", frt_sea_search, -1);
4028
- rb_define_method(cSearcher, "search_each", frt_sea_search_each, -1);
4029
- rb_define_method(cSearcher, "explain", frt_sea_explain, 2);
4030
- rb_define_method(cSearcher, "highlight", frt_sea_highlight, -1);
4396
+ rb_define_alloc_func(cSearcher, frb_data_alloc);
4397
+
4398
+ rb_define_method(cSearcher, "initialize", frb_sea_init, 1);
4399
+ rb_define_method(cSearcher, "close", frb_sea_close, 0);
4400
+ rb_define_method(cSearcher, "reader", frb_sea_get_reader, 0);
4401
+ rb_define_method(cSearcher, "doc_freq", frb_sea_doc_freq, 2);
4402
+ rb_define_method(cSearcher, "get_document", frb_sea_doc, 1);
4403
+ rb_define_method(cSearcher, "[]", frb_sea_doc, 1);
4404
+ rb_define_method(cSearcher, "max_doc", frb_sea_max_doc, 0);
4405
+ rb_define_method(cSearcher, "search", frb_sea_search, -1);
4406
+ rb_define_method(cSearcher, "search_each", frb_sea_search_each, -1);
4407
+ rb_define_method(cSearcher, "scan", frb_sea_scan, -1);
4408
+ rb_define_method(cSearcher, "explain", frb_sea_explain, 2);
4409
+ rb_define_method(cSearcher, "highlight", frb_sea_highlight, -1);
4031
4410
  }
4032
4411
 
4033
4412
  /*
@@ -4046,8 +4425,8 @@ static void
4046
4425
  Init_MultiSearcher(void)
4047
4426
  {
4048
4427
  cMultiSearcher = rb_define_class_under(mSearch, "MultiSearcher", cSearcher);
4049
- rb_define_alloc_func(cMultiSearcher, frt_data_alloc);
4050
- rb_define_method(cMultiSearcher, "initialize", frt_ms_init, -1);
4428
+ rb_define_alloc_func(cMultiSearcher, frb_data_alloc);
4429
+ rb_define_method(cMultiSearcher, "initialize", frb_ms_init, -1);
4051
4430
  }
4052
4431
 
4053
4432
  /*
@@ -4071,6 +4450,8 @@ Init_Search(void)
4071
4450
  {
4072
4451
  mSearch = rb_define_module_under(mFerret, "Search");
4073
4452
 
4453
+ fsym_id = I("id");
4454
+
4074
4455
  Init_Hit();
4075
4456
  Init_TopDocs();
4076
4457
  Init_Explanation();
@@ -4082,6 +4463,7 @@ Init_Search(void)
4082
4463
  Init_MultiTermQuery();
4083
4464
  Init_BooleanQuery();
4084
4465
  Init_RangeQuery();
4466
+ Init_TypedRangeQuery();
4085
4467
  Init_PhraseQuery();
4086
4468
  Init_PrefixQuery();
4087
4469
  Init_WildcardQuery();
@@ -4095,6 +4477,7 @@ Init_Search(void)
4095
4477
  /* Filters */
4096
4478
  Init_Filter();
4097
4479
  Init_RangeFilter();
4480
+ Init_TypedRangeFilter();
4098
4481
  Init_QueryFilter();
4099
4482
 
4100
4483
  /* Sorting */