ferret 0.3.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }