ferret 0.3.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/CHANGELOG +9 -0
  2. data/Rakefile +51 -25
  3. data/ext/analysis.c +553 -0
  4. data/ext/analysis.h +76 -0
  5. data/ext/array.c +83 -0
  6. data/ext/array.h +19 -0
  7. data/ext/bitvector.c +164 -0
  8. data/ext/bitvector.h +29 -0
  9. data/ext/compound_io.c +335 -0
  10. data/ext/document.c +336 -0
  11. data/ext/document.h +87 -0
  12. data/ext/ferret.c +88 -47
  13. data/ext/ferret.h +43 -109
  14. data/ext/field.c +395 -0
  15. data/ext/filter.c +103 -0
  16. data/ext/fs_store.c +352 -0
  17. data/ext/global.c +219 -0
  18. data/ext/global.h +73 -0
  19. data/ext/hash.c +446 -0
  20. data/ext/hash.h +80 -0
  21. data/ext/hashset.c +141 -0
  22. data/ext/hashset.h +37 -0
  23. data/ext/helper.c +11 -0
  24. data/ext/helper.h +5 -0
  25. data/ext/inc/lang.h +41 -0
  26. data/ext/ind.c +389 -0
  27. data/ext/index.h +884 -0
  28. data/ext/index_io.c +269 -415
  29. data/ext/index_rw.c +2543 -0
  30. data/ext/lang.c +31 -0
  31. data/ext/lang.h +41 -0
  32. data/ext/priorityqueue.c +228 -0
  33. data/ext/priorityqueue.h +44 -0
  34. data/ext/q_boolean.c +1331 -0
  35. data/ext/q_const_score.c +154 -0
  36. data/ext/q_fuzzy.c +287 -0
  37. data/ext/q_match_all.c +142 -0
  38. data/ext/q_multi_phrase.c +343 -0
  39. data/ext/q_parser.c +2180 -0
  40. data/ext/q_phrase.c +657 -0
  41. data/ext/q_prefix.c +75 -0
  42. data/ext/q_range.c +247 -0
  43. data/ext/q_span.c +1566 -0
  44. data/ext/q_term.c +308 -0
  45. data/ext/q_wildcard.c +146 -0
  46. data/ext/r_analysis.c +255 -0
  47. data/ext/r_doc.c +578 -0
  48. data/ext/r_index_io.c +996 -0
  49. data/ext/r_qparser.c +158 -0
  50. data/ext/r_search.c +2321 -0
  51. data/ext/r_store.c +263 -0
  52. data/ext/r_term.c +219 -0
  53. data/ext/ram_store.c +447 -0
  54. data/ext/search.c +524 -0
  55. data/ext/search.h +1065 -0
  56. data/ext/similarity.c +143 -39
  57. data/ext/sort.c +661 -0
  58. data/ext/store.c +35 -0
  59. data/ext/store.h +152 -0
  60. data/ext/term.c +704 -143
  61. data/ext/termdocs.c +599 -0
  62. data/ext/vector.c +594 -0
  63. data/lib/ferret.rb +9 -10
  64. data/lib/ferret/analysis/analyzers.rb +2 -2
  65. data/lib/ferret/analysis/standard_tokenizer.rb +1 -1
  66. data/lib/ferret/analysis/token.rb +14 -14
  67. data/lib/ferret/analysis/token_filters.rb +3 -3
  68. data/lib/ferret/document/field.rb +16 -17
  69. data/lib/ferret/index/document_writer.rb +4 -4
  70. data/lib/ferret/index/index.rb +39 -23
  71. data/lib/ferret/index/index_writer.rb +2 -2
  72. data/lib/ferret/index/multiple_term_doc_pos_enum.rb +1 -8
  73. data/lib/ferret/index/segment_term_vector.rb +4 -4
  74. data/lib/ferret/index/term.rb +5 -1
  75. data/lib/ferret/index/term_vector_offset_info.rb +6 -6
  76. data/lib/ferret/index/term_vectors_io.rb +5 -5
  77. data/lib/ferret/query_parser/query_parser.tab.rb +81 -77
  78. data/lib/ferret/search.rb +1 -1
  79. data/lib/ferret/search/boolean_query.rb +2 -1
  80. data/lib/ferret/search/field_sorted_hit_queue.rb +3 -3
  81. data/lib/ferret/search/fuzzy_query.rb +2 -1
  82. data/lib/ferret/search/index_searcher.rb +3 -0
  83. data/lib/ferret/search/{match_all_docs_query.rb → match_all_query.rb} +7 -7
  84. data/lib/ferret/search/multi_phrase_query.rb +6 -5
  85. data/lib/ferret/search/phrase_query.rb +3 -6
  86. data/lib/ferret/search/prefix_query.rb +4 -4
  87. data/lib/ferret/search/sort.rb +3 -1
  88. data/lib/ferret/search/sort_field.rb +9 -9
  89. data/lib/ferret/search/spans/near_spans_enum.rb +1 -1
  90. data/lib/ferret/search/spans/span_near_query.rb +1 -1
  91. data/lib/ferret/search/spans/span_weight.rb +1 -1
  92. data/lib/ferret/search/spans/spans_enum.rb +7 -7
  93. data/lib/ferret/store/fs_store.rb +10 -6
  94. data/lib/ferret/store/ram_store.rb +3 -3
  95. data/lib/rferret.rb +36 -0
  96. data/test/functional/thread_safety_index_test.rb +2 -2
  97. data/test/test_helper.rb +16 -2
  98. data/test/unit/analysis/c_token.rb +25 -0
  99. data/test/unit/analysis/tc_per_field_analyzer_wrapper.rb +1 -1
  100. data/test/unit/analysis/tc_standard_analyzer.rb +1 -1
  101. data/test/unit/document/{tc_document.rb → c_document.rb} +0 -0
  102. data/test/unit/document/c_field.rb +98 -0
  103. data/test/unit/document/tc_field.rb +0 -66
  104. data/test/unit/index/{tc_index.rb → c_index.rb} +62 -6
  105. data/test/unit/index/{tc_index_reader.rb → c_index_reader.rb} +51 -10
  106. data/test/unit/index/{tc_index_writer.rb → c_index_writer.rb} +0 -4
  107. data/test/unit/index/{tc_term.rb → c_term.rb} +1 -3
  108. data/test/unit/index/{tc_term_vector_offset_info.rb → c_term_voi.rb} +5 -5
  109. data/test/unit/index/tc_segment_term_vector.rb +2 -2
  110. data/test/unit/index/tc_term_vectors_io.rb +4 -4
  111. data/test/unit/query_parser/c_query_parser.rb +138 -0
  112. data/test/unit/search/{tc_filter.rb → c_filter.rb} +24 -24
  113. data/test/unit/search/{tc_fuzzy_query.rb → c_fuzzy_query.rb} +0 -0
  114. data/test/unit/search/{tc_index_searcher.rb → c_index_searcher.rb} +9 -26
  115. data/test/unit/search/{tc_search_and_sort.rb → c_search_and_sort.rb} +15 -15
  116. data/test/unit/search/{tc_sort.rb → c_sort.rb} +2 -1
  117. data/test/unit/search/c_sort_field.rb +27 -0
  118. data/test/unit/search/{tc_spans.rb → c_spans.rb} +0 -0
  119. data/test/unit/search/tc_sort_field.rb +7 -20
  120. data/test/unit/store/c_fs_store.rb +76 -0
  121. data/test/unit/store/c_ram_store.rb +35 -0
  122. data/test/unit/store/m_store.rb +34 -0
  123. data/test/unit/store/m_store_lock.rb +68 -0
  124. data/test/unit/store/tc_fs_store.rb +0 -53
  125. data/test/unit/store/tc_ram_store.rb +0 -20
  126. data/test/unit/store/tm_store.rb +0 -30
  127. data/test/unit/store/tm_store_lock.rb +0 -66
  128. metadata +84 -31
  129. data/ext/Makefile +0 -140
  130. data/ext/ferret_ext.so +0 -0
  131. data/ext/priority_queue.c +0 -232
  132. data/ext/ram_directory.c +0 -321
  133. data/ext/segment_merge_queue.c +0 -37
  134. data/ext/segment_term_enum.c +0 -326
  135. data/ext/string_helper.c +0 -42
  136. data/ext/tags +0 -344
  137. data/ext/term_buffer.c +0 -230
  138. data/ext/term_infos_reader.c +0 -54
  139. data/ext/terminfo.c +0 -160
  140. data/ext/token.c +0 -93
  141. data/ext/util.c +0 -12
data/ext/r_qparser.c ADDED
@@ -0,0 +1,158 @@
1
+ #include "ferret.h"
2
+ #include "search.h"
3
+
4
+ static VALUE cQueryParser;
5
+ VALUE cQueryParseException;
6
+
7
+ VALUE rhandle_parse_errors_key;
8
+ VALUE rallow_any_fields_key;
9
+ VALUE rwild_lower_key;
10
+ VALUE roccur_default_key;
11
+ VALUE rdefault_slop_key;
12
+ VALUE ranalyzer_key;
13
+
14
+ extern VALUE frt_get_analyzer(Analyzer *a);
15
+ extern VALUE frt_get_q(Query *q);
16
+
17
+ /****************************************************************************
18
+ *
19
+ * QueryParser Methods
20
+ *
21
+ ****************************************************************************/
22
+
23
+ static void
24
+ frt_qp_free(void *p)
25
+ {
26
+ QParser *qp = (QParser *)p;
27
+ object_del(p);
28
+ qp_destroy(qp);
29
+ }
30
+
31
+ static void
32
+ frt_qp_mark(void *p)
33
+ {
34
+ QParser *qp = (QParser *)p;
35
+ frt_gc_mark(qp->analyzer);
36
+ }
37
+
38
+ HashSet *
39
+ frt_get_fields(VALUE rfields)
40
+ {
41
+ VALUE rval;
42
+ HashSet *fields = hs_str_create(&free);
43
+ char *s, *p, *str;
44
+
45
+ if (TYPE(rfields) == T_ARRAY) {
46
+ int i;
47
+ for (i = 0; i < RARRAY(rfields)->len; i++) {
48
+ rval = rb_obj_as_string(RARRAY(rfields)->ptr[i]);
49
+ hs_add(fields, estrdup(RSTRING(rval)->ptr));
50
+ }
51
+ } else {
52
+ rval = rb_obj_as_string(rfields);
53
+ if (strcmp("*", RSTRING(rval)->ptr) == 0) {
54
+ hs_destroy(fields);
55
+ fields = NULL;
56
+ } else {
57
+ s = str = estrdup(RSTRING(rval)->ptr);
58
+ while ((p = index(s, '|'))) {
59
+ *p = '\0';
60
+ hs_add(fields, estrdup(s));
61
+ s = p + 1;
62
+ }
63
+ hs_add(fields, estrdup(s));
64
+ free(str);
65
+ }
66
+ }
67
+ return fields;
68
+ }
69
+
70
+ static VALUE
71
+ frt_qp_init(int argc, VALUE *argv, VALUE self)
72
+ {
73
+ VALUE rdef_field, roptions;
74
+ VALUE rval;
75
+ Analyzer *analyzer = NULL;
76
+
77
+ HashSet *all_fields = hs_str_create(&free);
78
+ HashSet *def_fields = NULL;
79
+ QParser *qp;
80
+
81
+ rb_scan_args(argc, argv, "02", &rdef_field, &roptions);
82
+ /* process default_field */
83
+ if (argc > 0) {
84
+ def_fields = frt_get_fields(rdef_field);
85
+ }
86
+ qp = qp_create(all_fields, def_fields, NULL);
87
+ qp->allow_any_fields = true;
88
+ qp->clean_str = true;
89
+ /* handle options */
90
+ if (argc == 2) {
91
+ if (Qnil != (rval = rb_hash_aref(roptions, rhandle_parse_errors_key))) {
92
+ qp->handle_parse_errors = RTEST(rval);
93
+ }
94
+ if (Qnil != (rval = rb_hash_aref(roptions, rallow_any_fields_key))) {
95
+ qp->allow_any_fields = RTEST(rval);
96
+ }
97
+ if (Qnil != (rval = rb_hash_aref(roptions, rwild_lower_key))) {
98
+ qp->wild_lower = RTEST(rval);
99
+ }
100
+ if (Qnil != (rval = rb_hash_aref(roptions, roccur_default_key))) {
101
+ qp->or_default = (FIX2INT(rval) == BC_MUST) ? false : true;
102
+ }
103
+ if (Qnil != (rval = rb_hash_aref(roptions, rdefault_slop_key))) {
104
+ qp->def_slop = FIX2INT(rval);
105
+ }
106
+ if (Qnil != (rval = rb_hash_aref(roptions, ranalyzer_key))) {
107
+ Data_Get_Struct(rval, Analyzer, analyzer);
108
+ }
109
+ }
110
+ if (!analyzer) {
111
+ analyzer = letter_analyzer_create();
112
+ /* make sure the analyzer will be disposed of when the QueryParser
113
+ * is garbage collected. */
114
+ rval = frt_get_analyzer(analyzer);
115
+ }
116
+ qp->analyzer = analyzer;
117
+ Frt_Wrap_Struct(self, frt_qp_mark, frt_qp_free, qp);
118
+ object_add(qp, self);
119
+ return self;
120
+ }
121
+
122
+ #define GET_QP QParser *qp; Data_Get_Struct(self, QParser, qp)
123
+ static VALUE
124
+ frt_qp_parse(VALUE self, VALUE rstr)
125
+ {
126
+ GET_QP;
127
+ rstr = rb_obj_as_string(rstr);
128
+ return frt_get_q(qp_parse(qp, RSTRING(rstr)->ptr));
129
+ }
130
+
131
+ /****************************************************************************
132
+ *
133
+ * Init function
134
+ *
135
+ ****************************************************************************/
136
+
137
+ void
138
+ Init_qparser(void)
139
+ {
140
+ /* hash keys */
141
+ rhandle_parse_errors_key = ID2SYM(rb_intern("handle_parse_errors"));
142
+ rallow_any_fields_key = ID2SYM(rb_intern("allow_any_fields"));
143
+ rwild_lower_key = ID2SYM(rb_intern("wild_lower"));
144
+ roccur_default_key = ID2SYM(rb_intern("occur_default"));
145
+ rdefault_slop_key = ID2SYM(rb_intern("default_slop"));
146
+ ranalyzer_key = ID2SYM(rb_intern("analyzer"));
147
+
148
+ /* QueryParser */
149
+ cQueryParser = rb_define_class_under(mFerret, "QueryParser", rb_cObject);
150
+ rb_define_alloc_func(cQueryParser, frt_data_alloc);
151
+
152
+ rb_define_method(cQueryParser, "initialize", frt_qp_init, -1);
153
+ rb_define_method(cQueryParser, "parse", frt_qp_parse, 1);
154
+
155
+ /* QueryParseException */
156
+ cQueryParseException = rb_define_class_under(cQueryParser,
157
+ "QueryParseException", rb_eStandardError);
158
+ }
data/ext/r_search.c ADDED
@@ -0,0 +1,2321 @@
1
+ #include "ferret.h"
2
+ #include <st.h>
3
+ #include <rubysig.h>
4
+ #include "search.h"
5
+
6
+ extern VALUE cTerm;
7
+ extern VALUE cDirectory;
8
+ extern VALUE cIndexReader;
9
+
10
+ static VALUE cScoreDoc;
11
+ static VALUE cTopDocs;
12
+ static VALUE cExplanation;
13
+ static VALUE cIndexSearcher;
14
+ static VALUE cSortField;
15
+ static VALUE cSortType;
16
+ static VALUE cSort;
17
+ static VALUE cIndex;
18
+
19
+ /* Queries */
20
+ static VALUE cQuery;
21
+ static VALUE cTermQuery;
22
+ static VALUE cBooleanQuery;
23
+ static VALUE cBooleanClause;
24
+ static VALUE cBCOccur;
25
+ static VALUE cRangeQuery;
26
+ static VALUE cPhraseQuery;
27
+ static VALUE cMultiPhraseQuery;
28
+ static VALUE cPrefixQuery;
29
+ static VALUE cWildCardQuery;
30
+ static VALUE cFuzzyQuery;
31
+ static VALUE cMatchAllQuery;
32
+ static VALUE cConstantScoreQuery;
33
+ static VALUE cSpanTermQuery;
34
+ static VALUE cSpanFirstQuery;
35
+ static VALUE cSpanNearQuery;
36
+ static VALUE cSpanOrQuery;
37
+ static VALUE cSpanNotQuery;
38
+
39
+ /* Filters */
40
+ static VALUE cFilter;
41
+ static VALUE cRangeFilter;
42
+ static VALUE cQueryFilter;
43
+
44
+ /* Option hash keys */
45
+ static VALUE rfirst_doc_key;
46
+ static VALUE rnum_docs_key;
47
+ static VALUE rfilter_key;
48
+ static VALUE rsort_key;
49
+
50
+ static VALUE rsort_type_key;
51
+ static VALUE rreverse_key;
52
+ static VALUE rcomparator_key;
53
+
54
+ static VALUE rpath_key;
55
+ static VALUE rcreate_key;
56
+ static VALUE rcreate_if_missing_key;
57
+ static VALUE rid_field_key;
58
+ static VALUE rdefault_field_key;
59
+ static VALUE rdefault_search_field_key;
60
+ static VALUE rdir_key;
61
+ static VALUE rclose_dir_key;
62
+ static VALUE rkey_key;
63
+ static VALUE ruse_compound_file_key;
64
+ static VALUE rauto_flush_key;
65
+ /* from r_qparser.c */
66
+ extern VALUE rhandle_parse_errors_key;
67
+ extern VALUE roccur_default_key;
68
+ extern VALUE rwild_lower_key;
69
+ extern VALUE rdefault_slop_key;
70
+ extern VALUE rallow_any_fields_key;
71
+ extern VALUE ranalyzer_key;
72
+
73
+ /* Class variable ids */
74
+ static VALUE rdefault_min_similarity_id;
75
+ static VALUE rdefault_prefix_length_id;
76
+
77
+ extern void frt_set_term(VALUE rterm, Term *t);
78
+ extern Term *frt_get_term(VALUE rterm);
79
+ extern VALUE frt_get_analyzer(Analyzer *a);
80
+ extern HashSet *frt_get_fields(VALUE rfields);
81
+
82
+ /****************************************************************************
83
+ *
84
+ * ScoreDoc Methods
85
+ *
86
+ ****************************************************************************/
87
+
88
+ static void
89
+ frt_sd_free(void *p)
90
+ {
91
+ object_del(p);
92
+ free(p);
93
+ }
94
+
95
+ static VALUE
96
+ frt_get_sd(Hit *hit)
97
+ {
98
+ VALUE self = Data_Wrap_Struct(cScoreDoc, NULL, &frt_sd_free, hit);
99
+ object_add(hit, self);
100
+ return self;
101
+ }
102
+
103
+ #define GET_HIT Hit *hit; Data_Get_Struct(self, Hit, hit)
104
+ static VALUE
105
+ frt_sd_score(VALUE self)
106
+ {
107
+ GET_HIT;
108
+ return rb_float_new(hit->score);
109
+ }
110
+
111
+ static VALUE
112
+ frt_sd_doc(VALUE self)
113
+ {
114
+ GET_HIT;
115
+ return INT2FIX(hit->doc);
116
+ }
117
+
118
+ /****************************************************************************
119
+ *
120
+ * TopDocs Methods
121
+ *
122
+ ****************************************************************************/
123
+
124
+ static void
125
+ frt_td_free(void *p)
126
+ {
127
+ TopDocs *td = (TopDocs *)p;
128
+ object_del(td);
129
+ if (td->hits) {
130
+ object_del(td->hits);
131
+ free(td->hits);
132
+ }
133
+ free(td);
134
+ }
135
+
136
+ static void
137
+ frt_td_mark(void *p)
138
+ {
139
+ TopDocs *td = (TopDocs *)p;
140
+ frt_gc_mark(td->hits);
141
+ }
142
+
143
+ #define GET_TD TopDocs *td; Data_Get_Struct(self, TopDocs, td)
144
+ static VALUE
145
+ frt_get_td(TopDocs *td)
146
+ {
147
+ int i;
148
+ VALUE self = Data_Wrap_Struct(cTopDocs, &frt_td_mark, &frt_td_free, td);
149
+ object_add(td, self);
150
+ if (td->hits) {
151
+ VALUE hits = rb_ary_new2(td->size);
152
+ for (i = 0; i < td->size; i++) {
153
+ rb_ary_store(hits, i, frt_get_sd(td->hits[i]));
154
+ }
155
+ object_add(td->hits, hits);
156
+ }
157
+ return self;
158
+ }
159
+
160
+ static VALUE
161
+ frt_td_hits(VALUE self)
162
+ {
163
+ GET_TD;
164
+ if (td->hits) {
165
+ return object_get(td->hits);
166
+ } else {
167
+ return rb_ary_new();
168
+ }
169
+ }
170
+
171
+ static VALUE
172
+ frt_td_size(VALUE self)
173
+ {
174
+ GET_TD;
175
+ return INT2FIX(td->size);
176
+ }
177
+
178
+ static VALUE
179
+ frt_td_total_hits(VALUE self)
180
+ {
181
+ GET_TD;
182
+ return INT2FIX(td->total_hits);
183
+ }
184
+
185
+ static VALUE
186
+ frt_td_fields(VALUE self)
187
+ {
188
+ GET_TD;
189
+ return Qnil;
190
+ }
191
+
192
+ static VALUE
193
+ frt_td_each(VALUE self)
194
+ {
195
+ int i;
196
+ Hit *hit;
197
+ GET_TD;
198
+ for (i = 0; i < td->size; i++) {
199
+ hit = td->hits[i];
200
+ rb_yield_values(2, INT2FIX(hit->doc), rb_float_new(hit->score));
201
+ }
202
+ return INT2FIX(td->size);
203
+ }
204
+
205
+ /****************************************************************************
206
+ *
207
+ * Explanation Methods
208
+ *
209
+ ****************************************************************************/
210
+
211
+ #define GET_EXPL Explanation *expl; Data_Get_Struct(self, Explanation, expl)
212
+ static VALUE
213
+ frt_expl_to_s(VALUE self)
214
+ {
215
+ GET_EXPL;
216
+ char *str = expl_to_s(expl, 0);
217
+ VALUE rstr = rb_str_new2(str);
218
+ free(str);
219
+ return rstr;
220
+ }
221
+
222
+ static VALUE
223
+ frt_expl_to_html(VALUE self)
224
+ {
225
+ GET_EXPL;
226
+ char *str = expl_to_html(expl);
227
+ VALUE rstr = rb_str_new2(str);
228
+ free(str);
229
+ return rstr;
230
+ }
231
+
232
+ static VALUE
233
+ frt_expl_value(VALUE self)
234
+ {
235
+ GET_EXPL;
236
+ return rb_float_new((double)expl->value);
237
+ }
238
+
239
+ /****************************************************************************
240
+ *
241
+ * Query Methods
242
+ *
243
+ ****************************************************************************/
244
+
245
+ static void
246
+ frt_q_free(void *p)
247
+ {
248
+ Query *q = (Query *)p;
249
+ object_del(p);
250
+ q->destroy(q);
251
+ }
252
+
253
+ #define GET_Q Query *q; Data_Get_Struct(self, Query, q)
254
+
255
+ static VALUE
256
+ frt_q_to_s(int argc, VALUE *argv, VALUE self)
257
+ {
258
+ VALUE rfield, rstr;
259
+ char *str, *field = "";
260
+ GET_Q;
261
+ if (rb_scan_args(argc, argv, "01", &rfield)) {
262
+ rfield = rb_obj_as_string(rfield);
263
+ field = RSTRING(rfield)->ptr;
264
+ }
265
+ str = q->to_s(q, field);
266
+ rstr = rb_str_new2(str);
267
+ free(str);
268
+ return rstr;
269
+ }
270
+
271
+ static VALUE
272
+ frt_q_get_boost(VALUE self)
273
+ {
274
+ GET_Q;
275
+ return rb_float_new((double)q->boost);
276
+ }
277
+
278
+ static VALUE
279
+ frt_q_set_boost(VALUE self, VALUE rboost)
280
+ {
281
+ GET_Q;
282
+ q->boost = NUM2DBL(rboost);
283
+ return rboost;
284
+ }
285
+
286
+ #define MK_QUERY(klass, q) Data_Wrap_Struct(klass, NULL, &frt_q_free, q)
287
+ VALUE
288
+ frt_get_q(Query *q)
289
+ {
290
+ VALUE self = object_get(q);
291
+
292
+ if (self == Qnil) {
293
+ switch (q->type) {
294
+ case TERM_QUERY:
295
+ self = MK_QUERY(cTermQuery, q);
296
+ break;
297
+ case BOOLEAN_QUERY:
298
+ self = MK_QUERY(cBooleanQuery, q);
299
+ break;
300
+ case PHRASE_QUERY:
301
+ self = MK_QUERY(cPhraseQuery, q);
302
+ break;
303
+ case MULTI_PHRASE_QUERY:
304
+ self = MK_QUERY(cMultiPhraseQuery, q);
305
+ break;
306
+ case CONSTANT_QUERY:
307
+ self = MK_QUERY(cConstantScoreQuery, q);
308
+ break;
309
+ case MATCH_ALL_QUERY:
310
+ self = MK_QUERY(cMatchAllQuery, q);
311
+ break;
312
+ case RANGE_QUERY:
313
+ self = MK_QUERY(cRangeQuery, q);
314
+ break;
315
+ case WILD_CARD_QUERY:
316
+ self = MK_QUERY(cWildCardQuery, q);
317
+ break;
318
+ case FUZZY_QUERY:
319
+ self = MK_QUERY(cFuzzyQuery, q);
320
+ break;
321
+ case PREFIX_QUERY:
322
+ self = MK_QUERY(cPrefixQuery, q);
323
+ break;
324
+ case SPAN_TERM_QUERY:
325
+ self = MK_QUERY(cSpanTermQuery, q);
326
+ break;
327
+ case SPAN_FIRST_QUERY:
328
+ self = MK_QUERY(cSpanFirstQuery, q);
329
+ break;
330
+ case SPAN_OR_QUERY:
331
+ self = MK_QUERY(cSpanOrQuery, q);
332
+ break;
333
+ case SPAN_NOT_QUERY:
334
+ self = MK_QUERY(cSpanNotQuery, q);
335
+ break;
336
+ case SPAN_NEAR_QUERY:
337
+ self = MK_QUERY(cSpanNearQuery, q);
338
+ break;
339
+ default:
340
+ self = MK_QUERY(cQuery, q);
341
+ break;
342
+ }
343
+ object_add(q, self);
344
+ }
345
+ return self;
346
+ }
347
+
348
+ /****************************************************************************
349
+ *
350
+ * TermQuery Methods
351
+ *
352
+ ****************************************************************************/
353
+
354
+ static VALUE
355
+ frt_tq_init(VALUE self, VALUE rterm)
356
+ {
357
+ Term *t = frt_get_term(rterm);
358
+ Query *q = tq_create(t);
359
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
360
+ object_add(q, self);
361
+ return self;
362
+ }
363
+
364
+ /****************************************************************************
365
+ *
366
+ * BooleanQuery Methods
367
+ *
368
+ ****************************************************************************/
369
+
370
+ static void
371
+ frt_bq_mark(void *p)
372
+ {
373
+ int i;
374
+ Query *q = (Query *)p;
375
+ BooleanQuery *bq = (BooleanQuery *)q->data;
376
+ for (i = 0; i < bq->clause_cnt; i++) {
377
+ frt_gc_mark(bq->clauses[i]->query);
378
+ }
379
+ }
380
+
381
+ static VALUE
382
+ frt_bq_init(int argc, VALUE *argv, VALUE self)
383
+ {
384
+ VALUE rcoord_disabled;
385
+ bool coord_disabled = false;
386
+ if (rb_scan_args(argc, argv, "01", &rcoord_disabled)) {
387
+ coord_disabled = RTEST(rcoord_disabled);
388
+ }
389
+ Query *q = bq_create(coord_disabled);
390
+ Frt_Wrap_Struct(self, &frt_bq_mark, &frt_q_free, q);
391
+ object_add(q, self);
392
+
393
+ /* don't destroy sub_queries as they are held by ruby objects */
394
+ q->destroy_all = false;
395
+ return self;
396
+ }
397
+
398
+ static VALUE
399
+ frt_bq_add_query(int argc, VALUE *argv, VALUE self)
400
+ {
401
+ GET_Q;
402
+ VALUE rquery, roccur;
403
+ int occur = BC_SHOULD;
404
+ Query *sub_q;
405
+ if (rb_scan_args(argc, argv, "11", &rquery, &roccur) == 2) {
406
+ occur = FIX2INT(roccur);
407
+ }
408
+ Data_Get_Struct(rquery, Query, sub_q);
409
+ bq_add_query(q, sub_q, occur);
410
+ return Qnil;
411
+ }
412
+
413
+ /****************************************************************************
414
+ *
415
+ * RangeQuery Methods
416
+ *
417
+ ****************************************************************************/
418
+
419
+ static VALUE
420
+ frt_rq_init(VALUE self, VALUE rfield, VALUE rlterm, VALUE ruterm,
421
+ VALUE rincl, VALUE rincu)
422
+ {
423
+ Query *q;
424
+ char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
425
+ char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
426
+ rfield = rb_obj_as_string(rfield);
427
+ q = rq_create(RSTRING(rfield)->ptr, lterm, uterm, RTEST(rincl), RTEST(rincu));
428
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
429
+ object_add(q, self);
430
+ return self;
431
+ }
432
+
433
+ static VALUE
434
+ frt_rq_new_more(VALUE klass, VALUE rfield, VALUE rlterm, VALUE rincl)
435
+ {
436
+ Query *q;
437
+ VALUE self;
438
+ rfield = rb_obj_as_string(rfield);
439
+ char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
440
+ q = rq_create_more(RSTRING(rfield)->ptr, lterm, RTEST(rincl));
441
+ self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
442
+ object_add(q, self);
443
+ return self;
444
+ }
445
+
446
+ static VALUE
447
+ frt_rq_new_less(VALUE klass, VALUE rfield, VALUE ruterm, VALUE rincu)
448
+ {
449
+ Query *q;
450
+ VALUE self;
451
+ rfield = rb_obj_as_string(rfield);
452
+ char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
453
+ q = rq_create_less(RSTRING(rfield)->ptr, uterm, RTEST(rincu));
454
+ self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
455
+ object_add(q, self);
456
+ return self;
457
+ }
458
+
459
+ /****************************************************************************
460
+ *
461
+ * PhraseQuery Methods
462
+ *
463
+ ****************************************************************************/
464
+
465
+ static VALUE
466
+ frt_phq_alloc(VALUE klass)
467
+ {
468
+ Query *q = phq_create();
469
+ VALUE self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
470
+ object_add(q, self);
471
+ return self;
472
+ }
473
+
474
+ static VALUE
475
+ frt_phq_init(VALUE self)
476
+ {
477
+ return self;
478
+ }
479
+
480
+ static VALUE
481
+ frt_phq_add(int argc, VALUE *argv, VALUE self)
482
+ {
483
+ VALUE rterm, rpos_inc;
484
+ int pos_inc = 1;
485
+ Term *t;
486
+ GET_Q;
487
+ if (rb_scan_args(argc, argv, "11", &rterm, &rpos_inc) == 2) {
488
+ pos_inc = FIX2INT(rpos_inc);
489
+ }
490
+ t = frt_get_term(rterm);
491
+ phq_add_term(q, t, pos_inc);
492
+ return self;
493
+ }
494
+
495
+ static VALUE
496
+ frt_phq_shift(VALUE self, VALUE rterm)
497
+ {
498
+ return frt_phq_add(1, &rterm, self);
499
+ }
500
+
501
+ static VALUE
502
+ frt_phq_get_slop(VALUE self)
503
+ {
504
+ GET_Q;
505
+ PhraseQuery *pq = (PhraseQuery *)q->data;
506
+ return INT2FIX(pq->slop);
507
+ }
508
+
509
+ static VALUE
510
+ frt_phq_set_slop(VALUE self, VALUE rslop)
511
+ {
512
+ GET_Q;
513
+ PhraseQuery *pq = (PhraseQuery *)q->data;
514
+ pq->slop = FIX2INT(rslop);
515
+ return self;
516
+ }
517
+
518
+ /****************************************************************************
519
+ *
520
+ * MultiPhraseQuery Methods
521
+ *
522
+ ****************************************************************************/
523
+
524
+ static VALUE
525
+ frt_mphq_alloc(VALUE klass)
526
+ {
527
+ Query *q = mphq_create();
528
+ VALUE self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
529
+ object_add(q, self);
530
+ return self;
531
+ }
532
+
533
+ static VALUE
534
+ frt_mphq_init(VALUE self)
535
+ {
536
+ return self;
537
+ }
538
+
539
+ static VALUE
540
+ frt_mphq_add(int argc, VALUE *argv, VALUE self)
541
+ {
542
+ VALUE rterms, rpos_inc;
543
+ int pos_inc = 1;
544
+ int t_cnt;
545
+ Term **terms;
546
+ GET_Q;
547
+ if (rb_scan_args(argc, argv, "11", &rterms, &rpos_inc) == 2) {
548
+ pos_inc = FIX2INT(rpos_inc);
549
+ }
550
+ if (TYPE(rterms) == T_ARRAY) {
551
+ int i;
552
+ t_cnt = RARRAY(rterms)->len;
553
+ terms = ALLOC_N(Term *, t_cnt);
554
+ for (i = 0; i < t_cnt; i++) {
555
+ terms[i] = frt_get_term(RARRAY(rterms)->ptr[i]);
556
+ }
557
+ } else {
558
+ Check_Type(rterms, T_DATA);
559
+ if (RBASIC(rterms)->klass != cTerm) {
560
+ rb_raise(rb_eArgError, "passed an unknown type to add");
561
+ }
562
+ t_cnt = 1;
563
+ terms = ALLOC_N(Term *, t_cnt);
564
+ terms[0] = frt_get_term(rterms);
565
+ }
566
+ mphq_add_terms(q, terms, t_cnt, pos_inc);
567
+ return self;
568
+ }
569
+
570
+ static VALUE
571
+ frt_mphq_shift(VALUE self, VALUE rterm)
572
+ {
573
+ return frt_mphq_add(1, &rterm, self);
574
+ }
575
+
576
+ static VALUE
577
+ frt_mphq_get_slop(VALUE self)
578
+ {
579
+ GET_Q;
580
+ MultiPhraseQuery *pq = (MultiPhraseQuery *)q->data;
581
+ return INT2FIX(pq->slop);
582
+ }
583
+
584
+ static VALUE
585
+ frt_mphq_set_slop(VALUE self, VALUE rslop)
586
+ {
587
+ GET_Q;
588
+ MultiPhraseQuery *pq = (MultiPhraseQuery *)q->data;
589
+ pq->slop = FIX2INT(rslop);
590
+ return self;
591
+ }
592
+
593
+
594
+ /****************************************************************************
595
+ *
596
+ * PrefixQuery Methods
597
+ *
598
+ ****************************************************************************/
599
+
600
+ static VALUE
601
+ frt_prq_init(VALUE self, VALUE rterm)
602
+ {
603
+ Term *t = frt_get_term(rterm);
604
+ Query *q = prefixq_create(t);
605
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
606
+ object_add(q, self);
607
+ return self;
608
+ }
609
+
610
+ /****************************************************************************
611
+ *
612
+ * WildCardQuery Methods
613
+ *
614
+ ****************************************************************************/
615
+
616
+ static VALUE
617
+ frt_wcq_init(VALUE self, VALUE rterm)
618
+ {
619
+ Term *t = frt_get_term(rterm);
620
+ Query *q = wcq_create(t);
621
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
622
+ object_add(q, self);
623
+ return self;
624
+ }
625
+
626
+ /****************************************************************************
627
+ *
628
+ * FuzzyQuery Methods
629
+ *
630
+ ****************************************************************************/
631
+
632
+ static VALUE
633
+ frt_fq_init(int argc, VALUE *argv, VALUE self)
634
+ {
635
+ Term *t;
636
+ Query *q;
637
+ VALUE rterm, rmin_sim, rpre_len;
638
+ FuzzyQuery *fq;
639
+ float min_sim;
640
+ int pre_len;
641
+ rb_scan_args(argc, argv, "12", &rterm, &rmin_sim, &rpre_len);
642
+ switch (argc) {
643
+ case 1:
644
+ rmin_sim = rb_cvar_get(cFuzzyQuery, rdefault_min_similarity_id);
645
+ case 2:
646
+ rpre_len = rb_cvar_get(cFuzzyQuery, rdefault_prefix_length_id);
647
+ }
648
+ min_sim = NUM2DBL(rmin_sim);
649
+ if (min_sim >= 1.0) {
650
+ rb_raise(rb_eArgError, "minimum_similarity cannot be greater than or equal to 1");
651
+ } else if (min_sim < 0.0) {
652
+ rb_raise(rb_eArgError, "minimum_similarity cannot be less than 0");
653
+ }
654
+ pre_len = INT2FIX(rpre_len);
655
+ if (pre_len < 0) {
656
+ rb_raise(rb_eArgError, "prefix_length cannot be less than 0");
657
+ }
658
+
659
+ t = frt_get_term(rterm);
660
+ q = fuzq_create(t);
661
+ fq = (FuzzyQuery *)q->data;
662
+
663
+ fq->pre_len = FIX2INT(rpre_len);
664
+ fq->min_sim = (float)NUM2DBL(rmin_sim);
665
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
666
+ object_add(q, self);
667
+ return self;
668
+ }
669
+
670
+ static VALUE
671
+ frt_fq_get_dms(VALUE self)
672
+ {
673
+ return rb_cvar_get(cFuzzyQuery, rdefault_min_similarity_id);
674
+ }
675
+
676
+ static VALUE
677
+ frt_fq_set_dms(VALUE self, VALUE val)
678
+ {
679
+ double min_sim = NUM2DBL(val);
680
+ if (min_sim >= 1.0) {
681
+ rb_raise(rb_eArgError, "minimum_similarity cannot be greater than or equal to 1");
682
+ } else if (min_sim < 0.0) {
683
+ rb_raise(rb_eArgError, "minimum_similarity cannot be less than 0");
684
+ }
685
+ rb_cvar_set(cFuzzyQuery, rdefault_min_similarity_id, val, Qfalse);
686
+ return val;
687
+ }
688
+
689
+ static VALUE
690
+ frt_fq_get_dpl(VALUE self)
691
+ {
692
+ return rb_cvar_get(cFuzzyQuery, rdefault_prefix_length_id);
693
+ }
694
+
695
+ static VALUE
696
+ frt_fq_set_dpl(VALUE self, VALUE val)
697
+ {
698
+ int pre_len = INT2FIX(val);
699
+ if (pre_len < 0) {
700
+ rb_raise(rb_eArgError, "prefix_length cannot be less than 0");
701
+ }
702
+ rb_cvar_set(cFuzzyQuery, rdefault_prefix_length_id, val, Qfalse);
703
+ return val;
704
+ }
705
+
706
+ /****************************************************************************
707
+ *
708
+ * MatchAllQuery Methods
709
+ *
710
+ ****************************************************************************/
711
+
712
+ static VALUE
713
+ frt_maq_alloc(VALUE klass)
714
+ {
715
+ Query *q = maq_create();
716
+ VALUE self = Data_Wrap_Struct(klass, NULL, &frt_q_free, q);
717
+ object_add(q, self);
718
+ return self;
719
+ }
720
+
721
+ static VALUE
722
+ frt_maq_init(VALUE self)
723
+ {
724
+ return self;
725
+ }
726
+
727
+ /****************************************************************************
728
+ *
729
+ * ConstantScoreQuery Methods
730
+ *
731
+ ****************************************************************************/
732
+
733
+ static VALUE
734
+ frt_csq_init(VALUE self, VALUE rfilter)
735
+ {
736
+ Query *q;
737
+ Filter *filter;
738
+ Data_Get_Struct(rfilter, Filter, filter);
739
+ q = csq_create(filter);
740
+
741
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
742
+ object_add(q, self);
743
+ return self;
744
+ }
745
+
746
+ /****************************************************************************
747
+ *
748
+ * SpanTermQuery Methods
749
+ *
750
+ ****************************************************************************/
751
+
752
+ static VALUE
753
+ frt_spantq_init(VALUE self, VALUE rterm)
754
+ {
755
+ Term *t = frt_get_term(rterm);
756
+ Query *q = spantq_create(t);
757
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
758
+ object_add(q, self);
759
+ return self;
760
+ }
761
+
762
+ /****************************************************************************
763
+ *
764
+ * SpanFirstQuery Methods
765
+ *
766
+ ****************************************************************************/
767
+
768
+ static VALUE
769
+ frt_spanfq_init(VALUE self, VALUE rmatch, VALUE rend)
770
+ {
771
+ Query *q;
772
+ Query *match;
773
+ Data_Get_Struct(rmatch, Query, match);
774
+ q = spanfq_create(match, FIX2INT(rend));
775
+ q->destroy_all = false;
776
+ Frt_Wrap_Struct(self, NULL, &frt_q_free, q);
777
+ object_add(q, self);
778
+ return self;
779
+ }
780
+
781
+ /****************************************************************************
782
+ *
783
+ * SpanNearQuery Methods
784
+ *
785
+ ****************************************************************************/
786
+
787
+ static void
788
+ frt_spannq_free(void *p)
789
+ {
790
+ SpanNearQuery *snq = (SpanNearQuery *)((SpanQuery *)((Query *)p)->data)->data;
791
+ free(snq->clauses);
792
+ frt_q_free(p);
793
+ }
794
+
795
+ static void
796
+ frt_spannq_mark(void *p)
797
+ {
798
+ int i;
799
+ SpanNearQuery *snq = (SpanNearQuery *)((SpanQuery *)((Query *)p)->data)->data;
800
+ for (i = 0; i < snq->c_cnt; i++) {
801
+ frt_gc_mark(snq->clauses[i]);
802
+ }
803
+ }
804
+
805
+ static VALUE
806
+ frt_spannq_init(VALUE self, VALUE rclauses, VALUE rslop, VALUE rin_order)
807
+ {
808
+ int i;
809
+ Query *q;
810
+ Query **clauses;
811
+ Check_Type(rclauses, T_ARRAY);
812
+ clauses = ALLOC_N(Query *, RARRAY(rclauses)->len);
813
+ for (i = 0; i < RARRAY(rclauses)->len; i++) {
814
+ Data_Get_Struct(RARRAY(rclauses)->ptr[i], Query, clauses[i]);
815
+ }
816
+
817
+ q = spannq_create(clauses, RARRAY(rclauses)->len,
818
+ FIX2INT(rslop), RTEST(rin_order));
819
+ q->destroy_all = false;
820
+ Frt_Wrap_Struct(self, &frt_spannq_mark, &frt_spannq_free, q);
821
+ object_add(q, self);
822
+ return self;
823
+ }
824
+
825
+ /****************************************************************************
826
+ *
827
+ * SpanOrQuery Methods
828
+ *
829
+ ****************************************************************************/
830
+
831
+ static void
832
+ frt_spanoq_free(void *p)
833
+ {
834
+ SpanOrQuery *soq = (SpanOrQuery *)((SpanQuery *)((Query *)p)->data)->data;
835
+ free(soq->clauses);
836
+ frt_q_free(p);
837
+ }
838
+
839
+ static void
840
+ frt_spanoq_mark(void *p)
841
+ {
842
+ int i;
843
+ SpanOrQuery *soq = (SpanOrQuery *)((SpanQuery *)((Query *)p)->data)->data;
844
+ for (i = 0; i < soq->c_cnt; i++) {
845
+ frt_gc_mark(soq->clauses[i]);
846
+ }
847
+ }
848
+
849
+ static VALUE
850
+ frt_spanoq_init(VALUE self, VALUE rclauses)
851
+ {
852
+ int i;
853
+ Query *q;
854
+ Query **clauses;
855
+ Check_Type(rclauses, T_ARRAY);
856
+ clauses = ALLOC_N(Query *, RARRAY(rclauses)->len);
857
+ for (i = 0; i < RARRAY(rclauses)->len; i++) {
858
+ Data_Get_Struct(RARRAY(rclauses)->ptr[i], Query, clauses[i]);
859
+ }
860
+
861
+ q = spanoq_create(clauses, RARRAY(rclauses)->len);
862
+ q->destroy_all = false;
863
+ Frt_Wrap_Struct(self, &frt_spanoq_mark, &frt_spanoq_free, q);
864
+ object_add(q, self);
865
+ return self;
866
+ }
867
+
868
+ /****************************************************************************
869
+ *
870
+ * SpanNotQuery Methods
871
+ *
872
+ ****************************************************************************/
873
+
874
+ static void
875
+ frt_spanxq_mark(void *p)
876
+ {
877
+ SpanNotQuery *sxq = (SpanNotQuery *)((SpanQuery *)((Query *)p)->data)->data;
878
+ frt_gc_mark(sxq->inc);
879
+ frt_gc_mark(sxq->exc);
880
+ }
881
+
882
+ static VALUE
883
+ frt_spanxq_init(VALUE self, VALUE rinc, VALUE rexc)
884
+ {
885
+ Check_Type(rinc, T_DATA);
886
+ Check_Type(rexc, T_DATA);
887
+ Query *q = spanxq_create(DATA_PTR(rinc), DATA_PTR(rexc));
888
+ q->destroy_all = false;
889
+ Frt_Wrap_Struct(self, &frt_spanxq_mark, &frt_q_free, q);
890
+ object_add(q, self);
891
+ return self;
892
+ }
893
+
894
+ /****************************************************************************
895
+ *
896
+ * Filter Methods
897
+ *
898
+ ****************************************************************************/
899
+
900
+ static void
901
+ frt_f_free(void *p)
902
+ {
903
+ Filter *f = (Filter *)p;
904
+ object_del(p);
905
+ f->destroy(f);
906
+ }
907
+
908
+ #define GET_F Filter *f; Data_Get_Struct(self, Filter, f)
909
+
910
+ static VALUE
911
+ frt_f_to_s(VALUE self)
912
+ {
913
+ VALUE rstr;
914
+ char *str;
915
+ GET_F;
916
+ str = f->to_s(f);
917
+ rstr = rb_str_new2(str);
918
+ free(str);
919
+ return rstr;
920
+ }
921
+
922
+ /****************************************************************************
923
+ *
924
+ * RangeFilter Methods
925
+ *
926
+ ****************************************************************************/
927
+
928
+ static VALUE
929
+ frt_rf_init(VALUE self, VALUE rfield, VALUE rlterm, VALUE ruterm,
930
+ VALUE rincl, VALUE rincu)
931
+ {
932
+ Filter *f;
933
+ char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
934
+ char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
935
+ rfield = rb_obj_as_string(rfield);
936
+ f = rfilt_create(RSTRING(rfield)->ptr, lterm, uterm, RTEST(rincl), RTEST(rincu));
937
+ Frt_Wrap_Struct(self, NULL, &frt_f_free, f);
938
+ object_add(f, self);
939
+ return self;
940
+ }
941
+
942
+ static VALUE
943
+ frt_rf_new_more(int argc, VALUE *argv, VALUE klass)
944
+ {
945
+ Filter *f;
946
+ VALUE self;
947
+ VALUE rfield, rlterm, rincl;
948
+ rb_scan_args(argc, argv, "21", &rfield, &rlterm, &rincl);
949
+ rfield = rb_obj_as_string(rfield);
950
+ char *lterm = NIL_P(rlterm) ? NULL : RSTRING(rb_obj_as_string(rlterm))->ptr;
951
+ f = rfilt_create(RSTRING(rfield)->ptr, lterm, NULL, rincl != Qfalse, false);
952
+ self = Data_Wrap_Struct(klass, NULL, &frt_f_free, f);
953
+ object_add(f, self);
954
+ return self;
955
+ }
956
+
957
+ static VALUE
958
+ frt_rf_new_less(int argc, VALUE *argv, VALUE klass)
959
+ {
960
+ Filter *f;
961
+ VALUE self;
962
+ VALUE rfield, ruterm, rincu;
963
+ rb_scan_args(argc, argv, "21", &rfield, &ruterm, &rincu);
964
+ rfield = rb_obj_as_string(rfield);
965
+ char *uterm = NIL_P(ruterm) ? NULL : RSTRING(rb_obj_as_string(ruterm))->ptr;
966
+ f = rfilt_create(RSTRING(rfield)->ptr, NULL, uterm, false, rincu != Qfalse);
967
+ self = Data_Wrap_Struct(klass, NULL, &frt_f_free, f);
968
+ object_add(f, self);
969
+ return self;
970
+ }
971
+
972
+ /****************************************************************************
973
+ *
974
+ * QueryFilter Methods
975
+ *
976
+ ****************************************************************************/
977
+
978
+ static VALUE
979
+ frt_qf_init(VALUE self, VALUE rquery)
980
+ {
981
+ Query *q;
982
+ Filter *f;
983
+ Data_Get_Struct(rquery, Query, q);
984
+ f = qfilt_create(q);
985
+ Frt_Wrap_Struct(self, NULL, &frt_f_free, f);
986
+ object_add(f, self);
987
+ return self;
988
+ }
989
+
990
+ /****************************************************************************
991
+ *
992
+ * SortField Methods
993
+ *
994
+ ****************************************************************************/
995
+
996
+ static void
997
+ frt_sf_free(void *p)
998
+ {
999
+ SortField *sf = (SortField *)p;
1000
+ object_del(sf);
1001
+ sort_field_destroy(sf);
1002
+ }
1003
+
1004
+ static VALUE
1005
+ frt_get_sf(SortField *sf)
1006
+ {
1007
+ VALUE self = object_get(sf);
1008
+ if (self == Qnil) {
1009
+ self = Data_Wrap_Struct(cSortField, NULL, &frt_sf_free, sf);
1010
+ object_add(sf, self);
1011
+ }
1012
+ return self;
1013
+ }
1014
+
1015
+ static VALUE
1016
+ frt_sf_init(int argc, VALUE *argv, VALUE self)
1017
+ {
1018
+ SortField *sf;
1019
+ VALUE rfield, roptions;
1020
+ VALUE rval;
1021
+ int sort_type = SORT_TYPE_AUTO;
1022
+ int is_reverse = false;
1023
+ if (rb_scan_args(argc, argv, "11", &rfield, &roptions) == 2) {
1024
+ if (Qnil != (rval = rb_hash_aref(roptions, rsort_type_key))) {
1025
+ sort_type = FIX2INT(rval);
1026
+ }
1027
+ if (Qnil != (rval = rb_hash_aref(roptions, rreverse_key))) {
1028
+ is_reverse = RTEST(rval);
1029
+ }
1030
+ if (Qnil != (rval = rb_hash_aref(roptions, rcomparator_key))) {
1031
+ rb_raise(rb_eArgError, "Unsupported argument ':comparator'");
1032
+ }
1033
+ }
1034
+ if (NIL_P(rfield)) rb_raise(rb_eArgError, "must pass a valid field name");
1035
+ rfield = rb_obj_as_string(rfield);
1036
+
1037
+ sf = sort_field_create(RSTRING(rfield)->ptr, sort_type, is_reverse);
1038
+
1039
+ Frt_Wrap_Struct(self, NULL, &frt_sf_free, sf);
1040
+ object_add(sf, self);
1041
+ return self;
1042
+ }
1043
+
1044
+ #define GET_SF SortField *sf; Data_Get_Struct(self, SortField, sf)
1045
+ static VALUE
1046
+ frt_sf_is_reverse(VALUE self)
1047
+ {
1048
+ GET_SF;
1049
+ return sf->reverse ? Qtrue : Qfalse;
1050
+ }
1051
+
1052
+ static VALUE
1053
+ frt_sf_get_name(VALUE self)
1054
+ {
1055
+ GET_SF;
1056
+ return sf->field ? rb_str_new2(sf->field) : Qnil;
1057
+ }
1058
+
1059
+ static VALUE
1060
+ frt_sf_get_sort_type(VALUE self)
1061
+ {
1062
+ GET_SF;
1063
+ return INT2FIX(sf->type);
1064
+ }
1065
+
1066
+ static VALUE
1067
+ frt_sf_get_comparator(VALUE self)
1068
+ {
1069
+ return Qnil;
1070
+ }
1071
+
1072
+ /****************************************************************************
1073
+ *
1074
+ * SortField Methods
1075
+ *
1076
+ ****************************************************************************/
1077
+
1078
+ static void
1079
+ frt_sort_free(void *p)
1080
+ {
1081
+ Sort *sort = (Sort *)p;
1082
+ object_del(sort);
1083
+ object_del(sort->sort_fields);
1084
+ sort_destroy(sort);
1085
+ }
1086
+
1087
+ static void
1088
+ frt_sort_mark(void *p)
1089
+ {
1090
+ Sort *sort = (Sort *)p;
1091
+ /*
1092
+ int i;
1093
+ for (i = 0; i < sort->sf_cnt; i++) {
1094
+ frt_get_sf(sort->sort_fields[i]);
1095
+ }
1096
+ */
1097
+ frt_gc_mark(sort->sort_fields);
1098
+ }
1099
+
1100
+ static VALUE
1101
+ frt_sort_alloc(VALUE klass)
1102
+ {
1103
+ VALUE self;
1104
+ Sort *sort = sort_create();
1105
+ sort->destroy_all = false;
1106
+ self = Data_Wrap_Struct(klass, &frt_sort_mark, &frt_sort_free, sort);
1107
+ object_add(sort, self);
1108
+ return self;
1109
+ }
1110
+
1111
+ static void
1112
+ frt_sort_add(Sort *sort, VALUE rsf, bool reverse)
1113
+ {
1114
+ SortField *sf;
1115
+ switch (TYPE(rsf)) {
1116
+ case T_DATA:
1117
+ Data_Get_Struct(rsf, SortField, sf);
1118
+ if (reverse) sf->reverse = !sf->reverse;
1119
+ break;
1120
+ case T_SYMBOL:
1121
+ rsf = rb_obj_as_string(rsf);
1122
+ case T_STRING:
1123
+ sf = sort_field_auto_create(RSTRING(rsf)->ptr, reverse);
1124
+ /* need to give it a ruby object so it'll be freed when the
1125
+ * sort is garbage collected */
1126
+ rsf = frt_get_sf(sf);
1127
+ break;
1128
+ default:
1129
+ rb_raise(rb_eArgError, "Unknown SortField Type");
1130
+ break;
1131
+ }
1132
+ sort_add_sort_field(sort, sf);
1133
+ }
1134
+
1135
+ #define GET_SORT Sort *sort; Data_Get_Struct(self, Sort, sort)
1136
+ static VALUE
1137
+ frt_sort_init(int argc, VALUE *argv, VALUE self)
1138
+ {
1139
+ int i;
1140
+ VALUE rfields, rreverse;
1141
+ bool reverse = false;
1142
+ bool has_sfd = false;
1143
+ GET_SORT;
1144
+ switch (rb_scan_args(argc, argv, "02", &rfields, &rreverse)) {
1145
+ case 2: reverse = RTEST(rreverse);
1146
+ case 1:
1147
+ if (TYPE(rfields) == T_ARRAY) {
1148
+ int i;
1149
+ for (i = 0; i < RARRAY(rfields)->len; i++) {
1150
+ frt_sort_add(sort, RARRAY(rfields)->ptr[i], reverse);
1151
+ }
1152
+ } else {
1153
+ frt_sort_add(sort, rfields, reverse);
1154
+ }
1155
+ for (i = 0; i < sort->sf_cnt; i++) {
1156
+ if (sort->sort_fields[i] == &SORT_FIELD_DOC) has_sfd = true;
1157
+ }
1158
+ if (!has_sfd) {
1159
+ sort_add_sort_field(sort, &SORT_FIELD_DOC);
1160
+ }
1161
+ break;
1162
+ case 0:
1163
+ sort_add_sort_field(sort, &SORT_FIELD_SCORE);
1164
+ sort_add_sort_field(sort, &SORT_FIELD_DOC);
1165
+ }
1166
+ rfields = rb_ary_new2(sort->sf_cnt);
1167
+ for (i = 0; i < sort->sf_cnt; i++) {
1168
+ rb_ary_store(rfields, i, object_get(sort->sort_fields[i]));
1169
+ }
1170
+ object_add(sort->sort_fields, rfields);
1171
+ return self;
1172
+ }
1173
+
1174
+ static VALUE
1175
+ frt_sort_get_fields(VALUE self)
1176
+ {
1177
+ GET_SORT;
1178
+ return object_get(sort->sort_fields);
1179
+ }
1180
+
1181
+ /****************************************************************************
1182
+ *
1183
+ * IndexSearcher Methods
1184
+ *
1185
+ ****************************************************************************/
1186
+
1187
+ static void
1188
+ frt_is_free(void *p)
1189
+ {
1190
+ Searcher *sea = (Searcher *)p;
1191
+ sea->close(sea);
1192
+ }
1193
+
1194
+ static void
1195
+ frt_is_mark(void *p)
1196
+ {
1197
+ Searcher *sea = (Searcher *)p;
1198
+ frt_gc_mark(sea->ir);
1199
+ frt_gc_mark(sea->ir->store);
1200
+ }
1201
+
1202
+ static VALUE
1203
+ frt_is_init(VALUE self, VALUE obj)
1204
+ {
1205
+ Store *store = NULL;
1206
+ IndexReader *ir = NULL;
1207
+ Searcher *sea;
1208
+ if (TYPE(obj) == T_STRING) {
1209
+ store = open_fs_store(StringValueCStr(obj));
1210
+ ir = ir_open(store, true);
1211
+ } else {
1212
+ Check_Type(obj, T_DATA);
1213
+ if (rb_obj_is_kind_of(obj, cDirectory) == Qtrue) {
1214
+ Data_Get_Struct(obj, Store, store);
1215
+ ir = ir_open(store, false);
1216
+ } else if (rb_obj_is_kind_of(obj, cIndexReader) == Qtrue) {
1217
+ Data_Get_Struct(obj, IndexReader, ir);
1218
+ } else {
1219
+ rb_raise(rb_eArgError, "Unknown type for argument to IndexSearcher.new");
1220
+ }
1221
+ }
1222
+
1223
+ sea = sea_create(ir);
1224
+ Frt_Wrap_Struct(self, &frt_is_mark, &frt_is_free, sea);
1225
+ return self;
1226
+ }
1227
+
1228
+ #define GET_SEA Searcher *sea; Data_Get_Struct(self, Searcher, sea)
1229
+
1230
+ static VALUE
1231
+ frt_is_close(VALUE self)
1232
+ {
1233
+ GET_SEA;
1234
+ Frt_Unwrap_Struct(self);
1235
+ sea->close(sea);
1236
+ return Qnil;
1237
+ }
1238
+
1239
+ static VALUE
1240
+ frt_is_doc_freq(VALUE self, VALUE rterm)
1241
+ {
1242
+ GET_SEA;
1243
+ Term t;
1244
+ frt_set_term(rterm, &t);
1245
+ return INT2FIX(sea->doc_freq(sea, &t));
1246
+ }
1247
+
1248
+ static VALUE
1249
+ frt_is_doc_freqs(VALUE self, VALUE rterms)
1250
+ {
1251
+ int i;
1252
+ GET_SEA;
1253
+ Term t;
1254
+ Check_Type(rterms, T_ARRAY);
1255
+ VALUE freqs = rb_ary_new2(RARRAY(rterms)->len);
1256
+ for (i = 0; i < RARRAY(rterms)->len; i++) {
1257
+ frt_set_term(RARRAY(rterms)->ptr[i], &t);
1258
+ rb_ary_store(freqs, i, INT2FIX(sea->doc_freq(sea, &t)));
1259
+ }
1260
+ return freqs;
1261
+ }
1262
+
1263
+ static VALUE
1264
+ frt_is_doc(VALUE self, VALUE rdoc_num)
1265
+ {
1266
+ GET_SEA;
1267
+ return frt_get_doc(sea->get_doc(sea, FIX2INT(rdoc_num)));
1268
+ }
1269
+
1270
+ static VALUE
1271
+ frt_is_max_doc(VALUE self)
1272
+ {
1273
+ GET_SEA;
1274
+ return INT2FIX(sea->max_doc(sea));
1275
+ }
1276
+
1277
+ static TopDocs *
1278
+ frt_is_search_internal(Query *query, VALUE roptions, Searcher *sea)
1279
+ {
1280
+ VALUE rval;
1281
+ int first_doc = 0, num_docs = 10;
1282
+ Filter *filter = NULL;
1283
+ Sort *sort = NULL;
1284
+
1285
+ if (Qnil != roptions) {
1286
+ if (Qnil != (rval = rb_hash_aref(roptions, rfirst_doc_key))) {
1287
+ first_doc = FIX2INT(rval);
1288
+ }
1289
+ if (Qnil != (rval = rb_hash_aref(roptions, rnum_docs_key))) {
1290
+ num_docs = FIX2INT(rval);
1291
+ }
1292
+ if (Qnil != (rval = rb_hash_aref(roptions, rfilter_key))) {
1293
+ Data_Get_Struct(rval, Filter, filter);
1294
+ }
1295
+ if (Qnil != (rval = rb_hash_aref(roptions, rsort_key))) {
1296
+ if (TYPE(rval) != T_DATA) {
1297
+ rval = frt_sort_init(1, &rval, frt_sort_alloc(cSort));
1298
+ }
1299
+ Data_Get_Struct(rval, Sort, sort);
1300
+ }
1301
+ }
1302
+
1303
+ return sea->search(sea, query, first_doc, num_docs, filter, sort);
1304
+ }
1305
+
1306
+ static VALUE
1307
+ frt_is_search(int argc, VALUE *argv, VALUE self)
1308
+ {
1309
+ GET_SEA;
1310
+ VALUE rquery, roptions;
1311
+ Query *query;
1312
+ rb_scan_args(argc, argv, "11", &rquery, &roptions);
1313
+ Data_Get_Struct(rquery, Query, query);
1314
+ return frt_get_td(frt_is_search_internal(query, roptions, sea));
1315
+ }
1316
+
1317
+ static VALUE
1318
+ frt_is_search_each(VALUE self, VALUE rquery, VALUE roptions)
1319
+ {
1320
+ return Qnil;
1321
+ }
1322
+
1323
+ static VALUE
1324
+ frt_is_explain(VALUE self, VALUE rquery, VALUE rdoc_num)
1325
+ {
1326
+ GET_SEA;
1327
+ Query *query;
1328
+ Data_Get_Struct(rquery, Query, query);
1329
+ Explanation *expl = sea->explain(sea, query, FIX2INT(rdoc_num));
1330
+ return Data_Wrap_Struct(cExplanation, NULL, &expl_destoy, expl);
1331
+ }
1332
+
1333
+ /****************************************************************************
1334
+ *
1335
+ * Index Methods
1336
+ *
1337
+ ****************************************************************************/
1338
+
1339
+ extern inline void ensure_searcher_open(Index *self);
1340
+ extern inline void ensure_reader_open(Index *self);
1341
+ extern inline void ensure_writer_open(Index *self);
1342
+
1343
+ static void
1344
+ frt_ind_free_store_i(Index *self)
1345
+ {
1346
+ VALUE rval;
1347
+ if (self->close_store && (Qnil != (rval = object_get(self->store)))) {
1348
+ /* user passed close_dir option so unwrap it */
1349
+ Frt_Unwrap_Struct(rval);
1350
+ object_del(self->store);
1351
+ }
1352
+ }
1353
+
1354
+ static void
1355
+ frt_ind_free(void *p)
1356
+ {
1357
+ Index *self = (Index *)p;
1358
+ frt_ind_free_store_i(self);
1359
+ object_del(self);
1360
+ index_destroy(self);
1361
+ }
1362
+
1363
+ static void
1364
+ frt_ind_mark(void *p)
1365
+ {
1366
+ Index *self = (Index *)p;
1367
+ frt_gc_mark(self->store);
1368
+ frt_gc_mark(self->analyzer);
1369
+ }
1370
+
1371
+ static VALUE
1372
+ frt_ind_init(int argc, VALUE *argv, VALUE self)
1373
+ {
1374
+ VALUE roptions;
1375
+ Index *ind;
1376
+ if (rb_scan_args(argc, argv, "01", &roptions)) {
1377
+ VALUE rval;
1378
+ Store *store = NULL;
1379
+ Analyzer *analyzer = NULL;
1380
+ bool create = false;
1381
+ bool close_store = false;
1382
+ HashSet *def_fields = NULL;
1383
+
1384
+ if (Qnil != (rval = rb_hash_aref(roptions, rpath_key))) {
1385
+ rval = rb_obj_as_string(rval);
1386
+ /* TODO: create the directory if it is missing */
1387
+ store = open_fs_store(RSTRING(rval)->ptr);
1388
+ close_store = true;
1389
+ } else if (Qnil != (rval = rb_hash_aref(roptions, rdir_key))) {
1390
+ Data_Get_Struct(rval, Store, store);
1391
+ }
1392
+ if (Qnil != (rval = rb_hash_aref(roptions, rcreate_key))) {
1393
+ create = RTEST(rval);
1394
+ }
1395
+ if (store) {
1396
+ if (!store->exists(store, "segments")) {
1397
+ if (Qfalse == rb_hash_aref(roptions, rcreate_if_missing_key)) {
1398
+ rb_raise(rb_eStandardError, "Index does not exist. Set either "
1399
+ ":create or :create_if_missing to true");
1400
+ } else {
1401
+ /* if create_if_missing and segments doesn't exist, create := true */
1402
+ create = true;
1403
+ }
1404
+ }
1405
+ } else {
1406
+ create = true;
1407
+ }
1408
+
1409
+ if (Qnil != (rval = rb_hash_aref(roptions, ranalyzer_key))) {
1410
+ Data_Get_Struct(rval, Analyzer, analyzer);
1411
+ }
1412
+ if (Qnil != (rval = rb_hash_aref(roptions, rdefault_search_field_key))) {
1413
+ def_fields = frt_get_fields(rval);
1414
+ }
1415
+ if (Qnil != (rval = rb_hash_aref(roptions, rclose_dir_key))) {
1416
+ if (RTEST(rval) && !close_store) close_store = true;
1417
+ }
1418
+ if (Qnil != (rval = rb_hash_aref(roptions, rdefault_field_key))) {
1419
+ if (!def_fields) def_fields = frt_get_fields(rval);
1420
+ }
1421
+ ind = index_create(store, analyzer, def_fields, create);
1422
+ if (close_store) ind->close_store = close_store;
1423
+
1424
+ /* QueryParser options */
1425
+ if (Qnil != (rval = rb_hash_aref(roptions, rhandle_parse_errors_key))) {
1426
+ ind->qp->handle_parse_errors = RTEST(rval);
1427
+ }
1428
+ if (Qnil != (rval = rb_hash_aref(roptions, rallow_any_fields_key))) {
1429
+ ind->qp->allow_any_fields = RTEST(rval);
1430
+ }
1431
+ if (Qnil != (rval = rb_hash_aref(roptions, rwild_lower_key))) {
1432
+ ind->qp->wild_lower = RTEST(rval);
1433
+ }
1434
+ if (Qnil != (rval = rb_hash_aref(roptions, roccur_default_key))) {
1435
+ ind->qp->or_default = (FIX2INT(rval) == BC_MUST) ? false : true;
1436
+ }
1437
+ if (Qnil != (rval = rb_hash_aref(roptions, rdefault_slop_key))) {
1438
+ ind->qp->def_slop = FIX2INT(rval);
1439
+ }
1440
+
1441
+ /* IndexWriter options */
1442
+ if (Qnil != (rval = rb_hash_aref(roptions, ruse_compound_file_key))) {
1443
+ ind->use_compound_file = RTEST(rval);
1444
+ if (ind->iw) ind->iw->use_compound_file = ind->use_compound_file;
1445
+ }
1446
+
1447
+ /* other options */
1448
+ /* by default id_field and def_field are the same but they can differ */
1449
+ if (Qnil != (rval = rb_hash_aref(roptions, rid_field_key))) {
1450
+ ind->id_field = estrdup(RSTRING(rb_obj_as_string(rval))->ptr);
1451
+ } else if (Qnil != (rval = rb_hash_aref(roptions, rdefault_field_key))) {
1452
+ ind->id_field = estrdup(RSTRING(rb_obj_as_string(rval))->ptr);
1453
+ }
1454
+ if (Qnil != (rval = rb_hash_aref(roptions, rdefault_field_key))) {
1455
+ ind->def_field = estrdup(RSTRING(rb_obj_as_string(rval))->ptr);
1456
+ } else if (Qnil != (rval = rb_hash_aref(roptions, rid_field_key))) {
1457
+ ind->def_field = estrdup(RSTRING(rb_obj_as_string(rval))->ptr);
1458
+ }
1459
+ if (Qnil != (rval = rb_hash_aref(roptions, rkey_key))) {
1460
+ ind->key = frt_get_fields(rval);
1461
+ }
1462
+ if (Qnil != (rval = rb_hash_aref(roptions, rauto_flush_key))) {
1463
+ ind->auto_flush = RTEST(rval);
1464
+ }
1465
+
1466
+ } else {
1467
+ ind = index_create(NULL, NULL, NULL, true);
1468
+ }
1469
+ Frt_Wrap_Struct(self, &frt_ind_mark, &frt_ind_free, ind);
1470
+ object_add(ind, self);
1471
+ return self;
1472
+ }
1473
+
1474
+ #define GET_IND Index *ind; Data_Get_Struct(self, Index, ind);\
1475
+ if (!ind) rb_raise(rb_eStandardError, "Called method on closed Index object")
1476
+ static VALUE
1477
+ frt_ind_close(VALUE self)
1478
+ {
1479
+ GET_IND;
1480
+ frt_ind_free_store_i(ind);
1481
+ Frt_Unwrap_Struct(self);
1482
+ object_del(ind);
1483
+ index_destroy(ind);
1484
+ return Qnil;
1485
+ }
1486
+
1487
+ static int
1488
+ frt_hash_to_doc_i(VALUE key, VALUE value, Document *doc)
1489
+ {
1490
+ VALUE rfield, rdata;
1491
+ if (key == Qundef) return ST_CONTINUE;
1492
+ rfield = rb_obj_as_string(key);
1493
+ rdata = rb_obj_as_string(value);
1494
+ doc_add_field(doc, df_create(RSTRING(rfield)->ptr, estrdup(RSTRING(rdata)->ptr),
1495
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1496
+ return ST_CONTINUE;
1497
+ }
1498
+
1499
+ static Document *
1500
+ frt_rdoc_to_doc(Index *ind, VALUE rdoc, bool *close_doc)
1501
+ {
1502
+ Document *doc = NULL;
1503
+ VALUE rstr;
1504
+ int i;
1505
+
1506
+ switch (TYPE(rdoc)) {
1507
+ case T_STRING:
1508
+ doc = doc_create();
1509
+ *close_doc = true;
1510
+ doc_add_field(doc, df_create(ind->def_field, estrdup(RSTRING(rdoc)->ptr),
1511
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1512
+ *close_doc = true;
1513
+ break;
1514
+ case T_ARRAY:
1515
+ doc = doc_create();
1516
+ *close_doc = true;
1517
+ for (i = 0; i < RARRAY(rdoc)->len; i++) {
1518
+ rstr = rb_obj_as_string(RARRAY(rdoc)->ptr[i]);
1519
+ doc_add_field(doc, df_create(ind->def_field, estrdup(RSTRING(rstr)->ptr),
1520
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1521
+ }
1522
+ break;
1523
+ case T_HASH:
1524
+ doc = doc_create();
1525
+ *close_doc = true;
1526
+ rb_hash_foreach(rdoc, frt_hash_to_doc_i, (VALUE)doc);
1527
+ break;
1528
+ case T_DATA:
1529
+ Data_Get_Struct(rdoc, Document, doc);
1530
+ break;
1531
+ default:
1532
+ rb_raise(rb_eArgError, "Can't add class %s to an Index", rb_obj_classname(rdoc));
1533
+ break;
1534
+ }
1535
+ return doc;
1536
+ }
1537
+
1538
+ static VALUE
1539
+ frt_ind_add_doc(int argc, VALUE *argv, VALUE self)
1540
+ {
1541
+ VALUE rdoc, ranalyzer;
1542
+ Document *doc;
1543
+ bool close_doc = false;
1544
+ GET_IND;
1545
+ rb_scan_args(argc, argv, "11", &rdoc, &ranalyzer);
1546
+
1547
+ doc = frt_rdoc_to_doc(ind, rdoc, &close_doc);
1548
+
1549
+ if (argc == 2) {
1550
+ Analyzer *analyzer;
1551
+ Data_Get_Struct(ranalyzer, Analyzer, analyzer);
1552
+ index_add_doc_a(ind, doc, analyzer);
1553
+ } else {
1554
+ index_add_doc(ind, doc);
1555
+ }
1556
+ if (close_doc) doc_destroy(doc);
1557
+ return self;
1558
+ }
1559
+
1560
+ static Query *
1561
+ frt_get_query_i(Index *ind, VALUE rquery, bool *destroy_query)
1562
+ {
1563
+ Query *q = NULL;
1564
+
1565
+ switch (TYPE(rquery)) {
1566
+ case T_STRING:
1567
+ q = index_get_query(ind, RSTRING(rquery)->ptr);
1568
+ *destroy_query = true;
1569
+ break;
1570
+ case T_DATA:
1571
+ Data_Get_Struct(rquery, Query, q);
1572
+ break;
1573
+ default:
1574
+ rb_raise(rb_eArgError, "Can only handle a String or a Query.");
1575
+ break;
1576
+ }
1577
+ //printf(">>>>>%s<<<<<\n", q->to_s(q, "def_field"));
1578
+ return q;
1579
+ }
1580
+
1581
+ static VALUE
1582
+ frt_ind_search(int argc, VALUE *argv, VALUE self)
1583
+ {
1584
+ Query *q;
1585
+ VALUE rquery, roptions, rtd;
1586
+ bool destroy_query = false;
1587
+ GET_IND;
1588
+ rb_scan_args(argc, argv, "11", &rquery, &roptions);
1589
+ ensure_searcher_open(ind);
1590
+
1591
+ q = frt_get_query_i(ind, rquery, &destroy_query);
1592
+ rtd = frt_get_td(frt_is_search_internal(q, roptions, ind->sea));
1593
+ if (destroy_query) q->destroy(q);
1594
+
1595
+ return rtd;
1596
+ }
1597
+
1598
+ static VALUE
1599
+ frt_ind_search_each(int argc, VALUE *argv, VALUE self)
1600
+ {
1601
+ int i;
1602
+ Query *q;
1603
+ TopDocs *td;
1604
+ VALUE rquery, roptions, rtotal_hits;
1605
+ bool destroy_query = false;
1606
+ GET_IND;
1607
+ rb_scan_args(argc, argv, "11", &rquery, &roptions);
1608
+ ensure_searcher_open(ind);
1609
+
1610
+ rb_thread_critical = Qtrue;
1611
+
1612
+ q = frt_get_query_i(ind, rquery, &destroy_query);
1613
+ td = frt_is_search_internal(q, roptions, ind->sea);
1614
+ if (destroy_query) q->destroy(q);
1615
+
1616
+ rtotal_hits = INT2FIX(td->total_hits);
1617
+ for (i = 0; i < td->size; i++) {
1618
+ if (index_is_deleted(ind, td->hits[i]->doc))
1619
+ rb_raise(rb_eStandardError, "FFFFFFFAAAAARRRRRRRRKKKKKKKKKKKKKKK");
1620
+ rb_yield_values(2, INT2FIX(td->hits[i]->doc),
1621
+ rb_float_new(td->hits[i]->score));
1622
+ }
1623
+
1624
+ rb_thread_critical = 0;
1625
+
1626
+ td_destroy(td);
1627
+ return rtotal_hits;
1628
+ }
1629
+
1630
+ static Document *
1631
+ frt_ind_doc_i(VALUE self, VALUE rid)
1632
+ {
1633
+ Document *doc = NULL;
1634
+ Term t;
1635
+ GET_IND;
1636
+ switch (TYPE(rid)) {
1637
+ case T_FIXNUM:
1638
+ doc = index_get_doc(ind, FIX2INT(rid));
1639
+ break;
1640
+ case T_STRING:
1641
+ doc = index_get_doc_id(ind, RSTRING(rid)->ptr);
1642
+ break;
1643
+ case T_DATA:
1644
+ frt_set_term(rid, &t);
1645
+ doc = index_get_doc_term(ind, &t);
1646
+ break;
1647
+ default:
1648
+ rb_raise(rb_eArgError, "cannot find id of type %s", rb_obj_classname(rid));
1649
+ break;
1650
+ }
1651
+ return doc;
1652
+ }
1653
+
1654
+ static VALUE
1655
+ frt_ind_doc(VALUE self, VALUE rid)
1656
+ {
1657
+ return frt_get_doc(frt_ind_doc_i(self, rid));
1658
+ }
1659
+
1660
+ static VALUE
1661
+ frt_ind_delete(VALUE self, VALUE rid)
1662
+ {
1663
+ Term t;
1664
+ GET_IND;
1665
+ switch (TYPE(rid)) {
1666
+ case T_FIXNUM:
1667
+ index_delete(ind, FIX2INT(rid));
1668
+ break;
1669
+ case T_STRING:
1670
+ index_delete_id(ind, RSTRING(rid)->ptr);
1671
+ break;
1672
+ case T_DATA:
1673
+ frt_set_term(rid, &t);
1674
+ index_delete_term(ind, &t);
1675
+ break;
1676
+ default:
1677
+ rb_raise(rb_eArgError, "cannot delete id of type %s", rb_obj_classname(rid));
1678
+ break;
1679
+ }
1680
+
1681
+ return INT2FIX(1);
1682
+ }
1683
+
1684
+ static VALUE
1685
+ frt_ind_query_delete(VALUE self, VALUE rquery)
1686
+ {
1687
+ Query *q;
1688
+ GET_IND;
1689
+ switch (TYPE(rquery)) {
1690
+ case T_STRING:
1691
+ index_delete_query_str(ind, RSTRING(rquery)->ptr, NULL);
1692
+ break;
1693
+ case T_DATA:
1694
+ Data_Get_Struct(rquery, Query, q);
1695
+ index_delete_query(ind, q, NULL);
1696
+ break;
1697
+ default:
1698
+ rb_raise(rb_eArgError, "Can only handle a String or a Query.");
1699
+ break;
1700
+ }
1701
+
1702
+ return self;
1703
+ }
1704
+
1705
+ static VALUE
1706
+ frt_ind_is_deleted(VALUE self, VALUE rdoc_num)
1707
+ {
1708
+ GET_IND;
1709
+ return index_is_deleted(ind, FIX2INT(rdoc_num)) ? Qtrue : Qfalse;
1710
+ }
1711
+
1712
+ static int
1713
+ frt_ind_get_doc_num_i(Index *ind, VALUE rid)
1714
+ {
1715
+ Term t;
1716
+ int doc_num = -1;
1717
+ switch (TYPE(rid)) {
1718
+ case T_FIXNUM:
1719
+ doc_num = FIX2INT(rid);
1720
+ break;
1721
+ case T_STRING:
1722
+ t.field = ind->id_field;
1723
+ t.text = RSTRING(rid)->ptr;
1724
+ doc_num = index_term_id(ind, &t);
1725
+ break;
1726
+ case T_DATA:
1727
+ frt_set_term(rid, &t);
1728
+ doc_num = index_term_id(ind, &t);
1729
+ break;
1730
+ default:
1731
+ rb_raise(rb_eArgError, "cannot find id of type %s", rb_obj_classname(rid));
1732
+ break;
1733
+ }
1734
+ return doc_num;
1735
+ }
1736
+
1737
+
1738
+ static int
1739
+ frt_hash_update_doc_i(VALUE key, VALUE value, Document *doc)
1740
+ {
1741
+ VALUE rfield, rdata;
1742
+ if (key == Qundef) return ST_CONTINUE;
1743
+ rfield = rb_obj_as_string(key);
1744
+ rdata = rb_obj_as_string(value);
1745
+ doc_delete_fields(doc, RSTRING(rfield)->ptr);
1746
+ doc_add_field(doc, df_create(RSTRING(rfield)->ptr, estrdup(RSTRING(rdata)->ptr),
1747
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1748
+ return ST_CONTINUE;
1749
+ }
1750
+
1751
+ static Document *
1752
+ frt_rdoc_update_doc(Index *ind, VALUE rdoc, Document *doc)
1753
+ {
1754
+ int i;
1755
+ VALUE rstr;
1756
+ Document *odoc;
1757
+ switch (TYPE(rdoc)) {
1758
+ case T_STRING:
1759
+ doc_delete_fields(doc, ind->def_field);
1760
+ doc_add_field(doc, df_create(ind->def_field, estrdup(RSTRING(rdoc)->ptr),
1761
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1762
+ break;
1763
+ case T_ARRAY:
1764
+ doc_delete_fields(doc, ind->def_field);
1765
+ for (i = 0; i < RARRAY(rdoc)->len; i++) {
1766
+ rstr = rb_obj_as_string(RARRAY(rdoc)->ptr[i]);
1767
+ doc_add_field(doc, df_create(ind->def_field, estrdup(RSTRING(rstr)->ptr),
1768
+ DF_STORE_YES, DF_INDEX_TOKENIZED, DF_TERM_VECTOR_NO));
1769
+ }
1770
+ break;
1771
+ case T_HASH:
1772
+ rb_hash_foreach(rdoc, frt_hash_update_doc_i, (VALUE)doc);
1773
+ break;
1774
+ case T_DATA:
1775
+ Data_Get_Struct(rdoc, Document, odoc);
1776
+ for (i = 0; i < odoc->fcnt; i++) {
1777
+ int j;
1778
+ char *field;
1779
+ Array *dfs = odoc->field_arr[i];
1780
+ field = ((DocField *)dfs->elems[0])->name;
1781
+ doc_delete_fields(doc, field);
1782
+ for (j = 0; j < dfs->size; j++) {
1783
+ doc_add_field(doc, df_clone((DocField *)dfs->elems[j]));
1784
+ }
1785
+ }
1786
+ break;
1787
+ default:
1788
+ rb_raise(rb_eArgError, "Can't add class %s to an Index", rb_obj_classname(rdoc));
1789
+ break;
1790
+ }
1791
+ return doc;
1792
+ }
1793
+
1794
+ static VALUE
1795
+ frt_ind_update(VALUE self, VALUE rid, VALUE rdoc)
1796
+ {
1797
+ int doc_num;
1798
+ GET_IND;
1799
+ doc_num = frt_ind_get_doc_num_i(ind, rid);
1800
+ if (doc_num >= 0) {
1801
+ Document *doc = index_get_doc(ind, doc_num);
1802
+ doc = frt_rdoc_update_doc(ind, rdoc, doc);
1803
+ index_delete(ind, doc_num);
1804
+ index_add_doc(ind, doc);
1805
+ doc_destroy(doc);
1806
+ index_auto_flush_iw(ind);
1807
+ }
1808
+ return self;
1809
+ }
1810
+
1811
+ struct QueryUpdateArg {
1812
+ Array *docs;
1813
+ VALUE rdoc;
1814
+ Index *ind;
1815
+ };
1816
+
1817
+ static void frt_ind_qupd_i(Searcher *sea, int doc_num, void *arg)
1818
+ {
1819
+ struct QueryUpdateArg *qua = (struct QueryUpdateArg *)arg;
1820
+ Document *doc = sea->ir->get_doc(sea->ir, doc_num);
1821
+ ir_delete_doc(sea->ir, doc_num);
1822
+ doc = frt_rdoc_update_doc(qua->ind, qua->rdoc, doc);
1823
+ ary_append(qua->docs, doc);
1824
+ }
1825
+
1826
+ static VALUE
1827
+ frt_ind_query_update(VALUE self, VALUE rquery, VALUE rdoc)
1828
+ {
1829
+ GET_IND;
1830
+
1831
+ int i;
1832
+ Query *q;
1833
+ bool destroy_query = false;
1834
+ struct QueryUpdateArg qua;
1835
+
1836
+
1837
+ ensure_searcher_open(ind);
1838
+ qua.rdoc = rdoc;
1839
+ qua.docs = ary_create(8, &doc_destroy);
1840
+ qua.ind = ind;
1841
+
1842
+ q = frt_get_query_i(ind, rquery, &destroy_query);
1843
+ sea_search_each(ind->sea, q, NULL, &frt_ind_qupd_i, &qua);
1844
+ if (destroy_query) q->destroy(q);
1845
+
1846
+ for (i = 0; i < qua.docs->size; i++) {
1847
+ index_add_doc(ind, qua.docs->elems[i]);
1848
+ }
1849
+
1850
+ ary_destroy(qua.docs);
1851
+
1852
+ index_auto_flush_ir(ind);
1853
+
1854
+ return self;
1855
+ }
1856
+
1857
+ static VALUE
1858
+ frt_ind_has_deletions(VALUE self)
1859
+ {
1860
+ GET_IND;
1861
+ return index_has_del(ind) ? Qtrue : Qfalse;
1862
+ }
1863
+
1864
+ static VALUE
1865
+ frt_ind_has_writes(VALUE self)
1866
+ {
1867
+ GET_IND;
1868
+ return ind->has_writes ? Qtrue : Qfalse;
1869
+ }
1870
+
1871
+ static VALUE
1872
+ frt_ind_flush(VALUE self)
1873
+ {
1874
+ GET_IND;
1875
+ index_flush(ind);
1876
+ return Qnil;
1877
+ }
1878
+
1879
+ static VALUE
1880
+ frt_ind_optimize(VALUE self)
1881
+ {
1882
+ GET_IND;
1883
+ index_optimize(ind);
1884
+ return Qnil;
1885
+ }
1886
+
1887
+ static VALUE
1888
+ frt_ind_size(VALUE self)
1889
+ {
1890
+ GET_IND;
1891
+ return INT2FIX(index_size(ind));
1892
+ }
1893
+
1894
+ #define INCONSISTANT_TYPES_MSG "Inconsistant arguments. All members "\
1895
+ "of indexes array must be of the same type"
1896
+ static void
1897
+ frt_ind_add_indexes_i(Index *ind, VALUE *indexes, int cnt)
1898
+ {
1899
+ int i;
1900
+ if (cnt == 0) return;
1901
+ Check_Type(indexes[0], T_DATA);
1902
+ if (rb_obj_is_kind_of(indexes[0], cDirectory) == Qtrue) {
1903
+ Store **stores = ALLOC_N(Store *, cnt);
1904
+ for (i = 0; i < cnt; i++) {
1905
+ if (rb_obj_is_kind_of(indexes[i], cDirectory) != Qtrue)
1906
+ rb_raise(rb_eArgError, INCONSISTANT_TYPES_MSG);
1907
+ Data_Get_Struct(indexes[i], Store, stores[i]);
1908
+ }
1909
+ ensure_writer_open(ind);
1910
+ iw_add_indexes(ind->iw, stores, cnt);
1911
+ free(stores);
1912
+ } else if (rb_obj_is_kind_of(indexes[0], cIndexReader) == Qtrue) {
1913
+ IndexReader **readers = ALLOC_N(IndexReader *, cnt);
1914
+ for (i = 0; i < cnt; i++) {
1915
+ if (rb_obj_is_kind_of(indexes[i], cIndexReader) != Qtrue)
1916
+ rb_raise(rb_eArgError, INCONSISTANT_TYPES_MSG);
1917
+ Data_Get_Struct(indexes[i], IndexReader, readers[i]);
1918
+ }
1919
+ ensure_writer_open(ind);
1920
+ iw_add_readers(ind->iw, readers, cnt);
1921
+ free(readers);
1922
+ } else if (CLASS_OF(indexes[0]) == cIndex) {
1923
+ Index *index;
1924
+ IndexReader **readers = ALLOC_N(IndexReader *, cnt);
1925
+ for (i = 0; i < cnt; i++) {
1926
+ if (CLASS_OF(indexes[i]) != cIndex)
1927
+ rb_raise(rb_eArgError, INCONSISTANT_TYPES_MSG);
1928
+ Data_Get_Struct(indexes[i], Index, index);
1929
+ ensure_reader_open(index);
1930
+ readers[i] = index->ir;
1931
+ }
1932
+ ensure_writer_open(ind);
1933
+ iw_add_readers(ind->iw, readers, cnt);
1934
+ free(readers);
1935
+ } else {
1936
+ rb_raise(rb_eArgError, "can't add class of type %s to index",
1937
+ rb_obj_classname(indexes[0]));
1938
+ }
1939
+
1940
+ index_auto_flush_iw(ind);
1941
+ }
1942
+
1943
+ static VALUE
1944
+ frt_ind_add_indexes(VALUE self, VALUE rindexes)
1945
+ {
1946
+ GET_IND;
1947
+ switch (TYPE(rindexes)) {
1948
+ case T_ARRAY:
1949
+ frt_ind_add_indexes_i(ind, RARRAY(rindexes)->ptr, RARRAY(rindexes)->len);
1950
+ break;
1951
+ default:
1952
+ frt_ind_add_indexes_i(ind, &rindexes, 1);
1953
+ break;
1954
+ }
1955
+ return self;
1956
+ }
1957
+
1958
+ static VALUE
1959
+ frt_ind_persist(int argc, VALUE *argv, VALUE self)
1960
+ {
1961
+ VALUE rdir, rcreate;
1962
+ bool create, close_store;
1963
+ Store *old_store;
1964
+ GET_IND;
1965
+
1966
+ index_flush(ind);
1967
+ frt_ind_free_store_i(ind);
1968
+ old_store = ind->store;
1969
+ close_store = ind->close_store;
1970
+
1971
+ rb_scan_args(argc, argv, "11", &rdir, &rcreate);
1972
+ create = RTEST(rcreate);
1973
+
1974
+ if (T_DATA == TYPE(rdir)) {
1975
+ Data_Get_Struct(rdir, Store, ind->store);
1976
+ } else {
1977
+ rdir = rb_obj_as_string(rdir);
1978
+ ind->store = open_fs_store(RSTRING(rdir)->ptr);
1979
+ ind->close_store = true;
1980
+ }
1981
+
1982
+ if (create) {
1983
+ ind->iw = iw_open(ind->store, NULL, create, false, false);
1984
+ ind->iw->use_compound_file = ind->use_compound_file;
1985
+ }
1986
+
1987
+ ensure_writer_open(ind);
1988
+ iw_add_indexes(ind->iw, &old_store, 1);
1989
+
1990
+ if (close_store) old_store->close(old_store);
1991
+
1992
+ index_auto_flush_iw(ind);
1993
+
1994
+ return self;
1995
+ }
1996
+
1997
+ static VALUE
1998
+ frt_ind_explain(VALUE self, VALUE rquery, VALUE rdoc_num)
1999
+ {
2000
+ GET_IND;
2001
+ bool destroy_query = false;
2002
+ Query *q = frt_get_query_i(ind, rquery, &destroy_query);
2003
+ Explanation *expl = index_explain(ind, q, FIX2INT(rdoc_num));
2004
+ if (destroy_query) q->destroy(q);
2005
+ return Data_Wrap_Struct(cExplanation, NULL, &expl_destoy, expl);
2006
+ }
2007
+
2008
+
2009
+ /****************************************************************************
2010
+ *
2011
+ * Init Function
2012
+ *
2013
+ ****************************************************************************/
2014
+
2015
+ void
2016
+ Init_search(void)
2017
+ {
2018
+ VALUE oSORT_FIELD_DOC;
2019
+
2020
+ /* option hash keys for IndexSearcher#search */
2021
+ rfirst_doc_key = ID2SYM(rb_intern("first_doc"));
2022
+ rnum_docs_key = ID2SYM(rb_intern("num_docs"));
2023
+ rfilter_key = ID2SYM(rb_intern("filter"));
2024
+ rsort_key = ID2SYM(rb_intern("sort"));
2025
+
2026
+
2027
+ /* option hash keys for SortField#initialize */
2028
+ rsort_type_key = ID2SYM(rb_intern("sort_type"));
2029
+ rreverse_key = ID2SYM(rb_intern("reverse"));
2030
+ rcomparator_key = ID2SYM(rb_intern("comparator"));
2031
+
2032
+ /* option hash keys for Index#initialize */
2033
+ rpath_key = ID2SYM(rb_intern("path"));
2034
+ rcreate_key = ID2SYM(rb_intern("create"));
2035
+ rcreate_if_missing_key = ID2SYM(rb_intern("create_if_missing"));
2036
+ rid_field_key = ID2SYM(rb_intern("id_field"));
2037
+ rdefault_field_key = ID2SYM(rb_intern("default_field"));
2038
+ rdefault_search_field_key = ID2SYM(rb_intern("default_search_field"));
2039
+ ranalyzer_key = ID2SYM(rb_intern("analyzer"));
2040
+ rdir_key = ID2SYM(rb_intern("dir"));
2041
+ rclose_dir_key = ID2SYM(rb_intern("close_dir"));
2042
+ rkey_key = ID2SYM(rb_intern("key"));
2043
+ ruse_compound_file_key = ID2SYM(rb_intern("use_compound_file"));
2044
+ rhandle_parse_errors_key = ID2SYM(rb_intern("handle_parse_errors"));
2045
+ rauto_flush_key = ID2SYM(rb_intern("auto_flush"));
2046
+
2047
+ /* ids */
2048
+ rdefault_min_similarity_id = rb_intern("default_min_similarity");
2049
+ rdefault_prefix_length_id = rb_intern("default_prefix_length");
2050
+
2051
+ /* Explanation */
2052
+ cExplanation = rb_define_class_under(mSearch, "Explanation", rb_cObject);
2053
+ rb_define_alloc_func(cExplanation, frt_data_alloc);
2054
+
2055
+ rb_define_method(cExplanation, "to_s", frt_expl_to_s, 0);
2056
+ rb_define_method(cExplanation, "to_html", frt_expl_to_html, 0);
2057
+ rb_define_method(cExplanation, "value", frt_expl_value, 0);
2058
+
2059
+ /* ScoreDoc */
2060
+ cScoreDoc = rb_define_class_under(mSearch, "ScoreDoc", rb_cObject);
2061
+ rb_define_alloc_func(cScoreDoc, frt_data_alloc);
2062
+
2063
+ rb_define_method(cScoreDoc, "score", frt_sd_score, 0);
2064
+ rb_define_method(cScoreDoc, "doc", frt_sd_doc, 0);
2065
+
2066
+ /* TopDocs */
2067
+ cTopDocs = rb_define_class_under(mSearch, "TopDocs", rb_cObject);
2068
+ rb_define_alloc_func(cTopDocs, frt_data_alloc);
2069
+
2070
+ rb_define_method(cTopDocs, "score_docs", frt_td_hits, 0);
2071
+ rb_define_method(cTopDocs, "hits", frt_td_hits, 0);
2072
+ rb_define_method(cTopDocs, "size", frt_td_size, 0);
2073
+ rb_define_method(cTopDocs, "total_hits", frt_td_total_hits, 0);
2074
+ rb_define_method(cTopDocs, "fields", frt_td_fields, 0);
2075
+ rb_define_method(cTopDocs, "each", frt_td_each, 0);
2076
+
2077
+ /* Query */
2078
+ cQuery = rb_define_class_under(mSearch, "Query", rb_cObject);
2079
+
2080
+ rb_define_method(cQuery, "to_s", frt_q_to_s, -1);
2081
+ rb_define_method(cQuery, "boost", frt_q_get_boost, 0);
2082
+ rb_define_method(cQuery, "boost=", frt_q_set_boost, 1);
2083
+
2084
+ /* TermQuery */
2085
+ cTermQuery = rb_define_class_under(mSearch, "TermQuery", cQuery);
2086
+ rb_define_alloc_func(cTermQuery, frt_data_alloc);
2087
+
2088
+ rb_define_method(cTermQuery, "initialize", frt_tq_init, 1);
2089
+
2090
+ /* BooleanQuery */
2091
+ cBooleanQuery = rb_define_class_under(mSearch, "BooleanQuery", cQuery);
2092
+ rb_define_alloc_func(cBooleanQuery, frt_data_alloc);
2093
+
2094
+ rb_define_method(cBooleanQuery, "initialize", frt_bq_init, -1);
2095
+ rb_define_method(cBooleanQuery, "add_query", frt_bq_add_query, -1);
2096
+
2097
+ rb_define_const(cBooleanQuery, "MUST", INT2FIX(BC_MUST));
2098
+ rb_define_const(cBooleanQuery, "MUST_NOT", INT2FIX(BC_MUST_NOT));
2099
+ rb_define_const(cBooleanQuery, "SHOULD", INT2FIX(BC_SHOULD));
2100
+
2101
+ /* BooleanQueryOccur */
2102
+ cBooleanClause = rb_define_class_under(mSearch, "BooleanClause", rb_cObject);
2103
+
2104
+ /* BooleanQueryOccur */
2105
+ cBCOccur = rb_define_class_under(cBooleanClause, "Occur", cQuery);
2106
+ rb_define_const(cBCOccur, "MUST", INT2FIX(BC_MUST));
2107
+ rb_define_const(cBCOccur, "MUST_NOT", INT2FIX(BC_MUST_NOT));
2108
+ rb_define_const(cBCOccur, "SHOULD", INT2FIX(BC_SHOULD));
2109
+
2110
+ /* RangeQuery */
2111
+ cRangeQuery = rb_define_class_under(mSearch, "RangeQuery", cQuery);
2112
+ rb_define_alloc_func(cRangeQuery, frt_data_alloc);
2113
+
2114
+ rb_define_method(cRangeQuery, "initialize", frt_rq_init, 5);
2115
+ rb_define_singleton_method(cRangeQuery, "new_more", frt_rq_new_more, 3);
2116
+ rb_define_singleton_method(cRangeQuery, "new_less", frt_rq_new_less, 3);
2117
+
2118
+ /* PhraseQuery */
2119
+ cPhraseQuery = rb_define_class_under(mSearch, "PhraseQuery", cQuery);
2120
+ rb_define_alloc_func(cPhraseQuery, frt_phq_alloc);
2121
+
2122
+ rb_define_method(cPhraseQuery, "initialize", frt_phq_init, 0);
2123
+ rb_define_method(cPhraseQuery, "add", frt_phq_add, -1);
2124
+ rb_define_method(cPhraseQuery, "<<", frt_phq_shift, 1);
2125
+ rb_define_method(cPhraseQuery, "slop", frt_phq_get_slop, 0);
2126
+ rb_define_method(cPhraseQuery, "slop=", frt_phq_set_slop, 1);
2127
+
2128
+ /* MultiPhraseQuery */
2129
+ cMultiPhraseQuery = rb_define_class_under(mSearch, "MultiPhraseQuery", cQuery);
2130
+ rb_define_alloc_func(cMultiPhraseQuery, frt_mphq_alloc);
2131
+
2132
+ rb_define_method(cMultiPhraseQuery, "initialize", frt_mphq_init, 0);
2133
+ rb_define_method(cMultiPhraseQuery, "add", frt_mphq_add, -1);
2134
+ rb_define_method(cMultiPhraseQuery, "<<", frt_mphq_shift, 1);
2135
+ rb_define_method(cMultiPhraseQuery, "slop", frt_mphq_get_slop, 0);
2136
+ rb_define_method(cMultiPhraseQuery, "slop=", frt_mphq_set_slop, 1);
2137
+
2138
+ /* PrefixQuery */
2139
+ cPrefixQuery = rb_define_class_under(mSearch, "PrefixQuery", cQuery);
2140
+ rb_define_alloc_func(cPrefixQuery, frt_data_alloc);
2141
+
2142
+ rb_define_method(cPrefixQuery, "initialize", frt_prq_init, 1);
2143
+
2144
+ /* WildCardQuery */
2145
+ cWildCardQuery = rb_define_class_under(mSearch, "WildcardQuery", cQuery);
2146
+ rb_define_alloc_func(cWildCardQuery, frt_data_alloc);
2147
+
2148
+ rb_define_method(cWildCardQuery, "initialize", frt_wcq_init, 1);
2149
+
2150
+ /* FuzzyQuery */
2151
+ cFuzzyQuery = rb_define_class_under(mSearch, "FuzzyQuery", cQuery);
2152
+ rb_define_alloc_func(cFuzzyQuery, frt_data_alloc);
2153
+ rb_cvar_set(cFuzzyQuery, rdefault_min_similarity_id, rb_float_new(0.5), Qfalse);
2154
+ rb_cvar_set(cFuzzyQuery, rdefault_prefix_length_id, INT2FIX(0), Qfalse);
2155
+
2156
+ rb_define_singleton_method(cFuzzyQuery, "default_min_similarity", frt_fq_get_dms, 0);
2157
+ rb_define_singleton_method(cFuzzyQuery, "default_min_similarity=", frt_fq_set_dms, 1);
2158
+ rb_define_singleton_method(cFuzzyQuery, "default_prefix_length", frt_fq_get_dpl, 0);
2159
+ rb_define_singleton_method(cFuzzyQuery, "default_prefix_length=", frt_fq_set_dpl, 1);
2160
+
2161
+ rb_define_method(cFuzzyQuery, "initialize", frt_fq_init, -1);
2162
+
2163
+ /* MatchAllQuery */
2164
+ cMatchAllQuery = rb_define_class_under(mSearch, "MatchAllQuery", cQuery);
2165
+ rb_define_alloc_func(cMatchAllQuery, frt_maq_alloc);
2166
+
2167
+ rb_define_method(cMatchAllQuery, "initialize", frt_maq_init, 0);
2168
+
2169
+ /* ConstantScoreQuery */
2170
+ cConstantScoreQuery = rb_define_class_under(mSearch, "ConstantScoreQuery", cQuery);
2171
+ rb_define_alloc_func(cConstantScoreQuery, frt_data_alloc);
2172
+
2173
+ rb_define_method(cConstantScoreQuery, "initialize", frt_csq_init, 1);
2174
+
2175
+ /* SpanTermQuery */
2176
+ cSpanTermQuery = rb_define_class_under(mSpans, "SpanTermQuery", cQuery);
2177
+ rb_define_alloc_func(cSpanTermQuery, frt_data_alloc);
2178
+
2179
+ rb_define_method(cSpanTermQuery, "initialize", frt_spantq_init, 1);
2180
+
2181
+ /* SpanFirstQuery */
2182
+ cSpanFirstQuery = rb_define_class_under(mSpans, "SpanFirstQuery", cQuery);
2183
+ rb_define_alloc_func(cSpanFirstQuery, frt_data_alloc);
2184
+
2185
+ rb_define_method(cSpanFirstQuery, "initialize", frt_spanfq_init, 2);
2186
+
2187
+ /* SpanNearQuery */
2188
+ cSpanNearQuery = rb_define_class_under(mSpans, "SpanNearQuery", cQuery);
2189
+ rb_define_alloc_func(cSpanNearQuery, frt_data_alloc);
2190
+
2191
+ rb_define_method(cSpanNearQuery, "initialize", frt_spannq_init, 3);
2192
+
2193
+ /* SpanOrQuery */
2194
+ cSpanOrQuery = rb_define_class_under(mSpans, "SpanOrQuery", cQuery);
2195
+ rb_define_alloc_func(cSpanOrQuery, frt_data_alloc);
2196
+
2197
+ rb_define_method(cSpanOrQuery, "initialize", frt_spanoq_init, 1);
2198
+
2199
+ /* SpanNotQuery */
2200
+ cSpanNotQuery = rb_define_class_under(mSpans, "SpanNotQuery", cQuery);
2201
+ rb_define_alloc_func(cSpanNotQuery, frt_data_alloc);
2202
+
2203
+ rb_define_method(cSpanNotQuery, "initialize", frt_spanxq_init, 2);
2204
+
2205
+
2206
+ /* Filter */
2207
+ cFilter = rb_define_class_under(mSearch, "Filter", rb_cObject);
2208
+ rb_define_alloc_func(cConstantScoreQuery, frt_data_alloc);
2209
+
2210
+ rb_define_method(cFilter, "to_s", frt_f_to_s, 0);
2211
+
2212
+ /* RangeFilter */
2213
+ cRangeFilter = rb_define_class_under(mSearch, "RangeFilter", cFilter);
2214
+ rb_define_alloc_func(cRangeFilter, frt_data_alloc);
2215
+
2216
+ rb_define_method(cRangeFilter, "initialize", frt_rf_init, 5);
2217
+ rb_define_singleton_method(cRangeFilter, "new_more", frt_rf_new_more, -1);
2218
+ rb_define_singleton_method(cRangeFilter, "new_less", frt_rf_new_less, -1);
2219
+
2220
+ /* QueryFilter */
2221
+ cQueryFilter = rb_define_class_under(mSearch, "QueryFilter", cFilter);
2222
+ rb_define_alloc_func(cQueryFilter, frt_data_alloc);
2223
+
2224
+ rb_define_method(cQueryFilter, "initialize", frt_qf_init, 1);
2225
+
2226
+ /* SortField */
2227
+ cSortField = rb_define_class_under(mSearch, "SortField", rb_cObject);
2228
+ rb_define_alloc_func(cSortField, frt_data_alloc);
2229
+
2230
+ rb_define_method(cSortField, "initialize", frt_sf_init, -1);
2231
+ rb_define_method(cSortField, "reverse?", frt_sf_is_reverse, 0);
2232
+ rb_define_method(cSortField, "name", frt_sf_get_name, 0);
2233
+ rb_define_method(cSortField, "sort_type", frt_sf_get_sort_type, 0);
2234
+ rb_define_method(cSortField, "comparator", frt_sf_get_comparator, 0);
2235
+
2236
+ /* SortType */
2237
+ cSortType = rb_define_class_under(cSortField, "SortType", rb_cObject);
2238
+ rb_define_alloc_func(cSortType, frt_data_alloc);
2239
+
2240
+ rb_define_const(cSortType, "SCORE", INT2FIX(SORT_TYPE_SCORE));
2241
+ rb_define_const(cSortType, "DOC", INT2FIX(SORT_TYPE_DOC));
2242
+ rb_define_const(cSortType, "AUTO", INT2FIX(SORT_TYPE_AUTO));
2243
+ rb_define_const(cSortType, "STRING", INT2FIX(SORT_TYPE_STRING));
2244
+ rb_define_const(cSortType, "INTEGER", INT2FIX(SORT_TYPE_INTEGER));
2245
+ rb_define_const(cSortType, "FLOAT", INT2FIX(SORT_TYPE_FLOAT));
2246
+
2247
+ rb_define_const(cSortField, "FIELD_SCORE",
2248
+ Data_Wrap_Struct(cSortField, NULL, &frt_deref_free, &SORT_FIELD_SCORE));
2249
+ object_add(&SORT_FIELD_SCORE, rb_const_get(cSortField, rb_intern("FIELD_SCORE")));
2250
+
2251
+ rb_define_const(cSortField, "FIELD_SCORE_REV",
2252
+ Data_Wrap_Struct(cSortField, NULL, &frt_deref_free, &SORT_FIELD_SCORE_REV));
2253
+ object_add(&SORT_FIELD_SCORE_REV,
2254
+ rb_const_get(cSortField, rb_intern("FIELD_SCORE_REV")));
2255
+
2256
+ rb_define_const(cSortField, "FIELD_DOC",
2257
+ Data_Wrap_Struct(cSortField, NULL, &frt_deref_free, &SORT_FIELD_DOC));
2258
+
2259
+ oSORT_FIELD_DOC = rb_const_get(cSortField, rb_intern("FIELD_DOC"));
2260
+ object_add(&SORT_FIELD_DOC, oSORT_FIELD_DOC);
2261
+
2262
+ rb_define_const(cSortField, "FIELD_DOC_REV",
2263
+ Data_Wrap_Struct(cSortField, NULL, &frt_deref_free, &SORT_FIELD_DOC_REV));
2264
+ object_add(&SORT_FIELD_DOC_REV,
2265
+ rb_const_get(cSortField, rb_intern("FIELD_DOC_REV")));
2266
+
2267
+ /* Sort */
2268
+ cSort = rb_define_class_under(mSearch, "Sort", rb_cObject);
2269
+ rb_define_alloc_func(cSort, frt_sort_alloc);
2270
+
2271
+ rb_define_method(cSort, "initialize", frt_sort_init, -1);
2272
+ rb_define_method(cSort, "fields", frt_sort_get_fields, 0);
2273
+
2274
+ rb_define_const(cSort, "RELEVANCE",
2275
+ frt_sort_init(0, NULL, frt_sort_alloc(cSort)));
2276
+ rb_define_const(cSort, "INDEX_ORDER",
2277
+ frt_sort_init(1, &oSORT_FIELD_DOC, frt_sort_alloc(cSort)));
2278
+
2279
+ /* IndexSearcher */
2280
+ cIndexSearcher = rb_define_class_under(mSearch, "IndexSearcher", rb_cObject);
2281
+ rb_define_alloc_func(cIndexSearcher, frt_data_alloc);
2282
+
2283
+ rb_define_method(cIndexSearcher, "initialize", frt_is_init, 1);
2284
+ rb_define_method(cIndexSearcher, "close", frt_is_close, 0);
2285
+ rb_define_method(cIndexSearcher, "doc_freq", frt_is_doc_freq, 1);
2286
+ rb_define_method(cIndexSearcher, "doc_freqs", frt_is_doc_freqs, 1);
2287
+ rb_define_method(cIndexSearcher, "doc", frt_is_doc, 1);
2288
+ rb_define_method(cIndexSearcher, "[]", frt_is_doc, 1);
2289
+ rb_define_method(cIndexSearcher, "max_doc", frt_is_max_doc, 0);
2290
+ rb_define_method(cIndexSearcher, "search", frt_is_search, -1);
2291
+ rb_define_method(cIndexSearcher, "search_each", frt_is_search_each, 2);
2292
+ rb_define_method(cIndexSearcher, "explain", frt_is_explain, 2);
2293
+
2294
+ /* Index */
2295
+ cIndex = rb_define_class_under(mIndex, "Index", rb_cObject);
2296
+ rb_define_alloc_func(cIndex, frt_data_alloc);
2297
+
2298
+ rb_define_method(cIndex, "initialize", frt_ind_init, -1);
2299
+ rb_define_method(cIndex, "close", frt_ind_close, 0);
2300
+ rb_define_method(cIndex, "add_document", frt_ind_add_doc, -1);
2301
+ rb_define_method(cIndex, "add_doc", frt_ind_add_doc, -1);
2302
+ rb_define_method(cIndex, "<<", frt_ind_add_doc, -1);
2303
+ rb_define_method(cIndex, "search", frt_ind_search, -1);
2304
+ rb_define_method(cIndex, "search_each", frt_ind_search_each, -1);
2305
+ rb_define_method(cIndex, "doc", frt_ind_doc, 1);
2306
+ rb_define_method(cIndex, "[]", frt_ind_doc, 1);
2307
+ rb_define_method(cIndex, "delete", frt_ind_delete, 1);
2308
+ rb_define_method(cIndex, "query_delete", frt_ind_query_delete, 1);
2309
+ rb_define_method(cIndex, "deleted?", frt_ind_is_deleted, 1);
2310
+ rb_define_method(cIndex, "update", frt_ind_update, 2);
2311
+ rb_define_method(cIndex, "query_update", frt_ind_query_update, 2);
2312
+ rb_define_method(cIndex, "has_deletions?", frt_ind_has_deletions, 0);
2313
+ rb_define_method(cIndex, "has_writes?", frt_ind_has_writes, 0);
2314
+ rb_define_method(cIndex, "flush", frt_ind_flush, 0);
2315
+ rb_define_method(cIndex, "optimize", frt_ind_optimize, 0);
2316
+ rb_define_method(cIndex, "size", frt_ind_size, 0);
2317
+ rb_define_method(cIndex, "num_docs", frt_ind_size, 0);
2318
+ rb_define_method(cIndex, "add_indexes", frt_ind_add_indexes, 1);
2319
+ rb_define_method(cIndex, "persist", frt_ind_persist, -1);
2320
+ rb_define_method(cIndex, "explain", frt_ind_explain, 2);
2321
+ }