ferret 0.9.1 → 0.9.2

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 (105) hide show
  1. data/README +6 -5
  2. data/Rakefile +34 -13
  3. data/TODO +1 -0
  4. data/TUTORIAL +1 -1
  5. data/ext/analysis.c +87 -70
  6. data/ext/analysis.h +18 -6
  7. data/ext/array.c +1 -2
  8. data/ext/array.h +1 -1
  9. data/ext/bitvector.c +10 -6
  10. data/ext/bitvector.h +2 -2
  11. data/ext/compound_io.c +30 -27
  12. data/ext/document.c +15 -15
  13. data/ext/document.h +5 -5
  14. data/ext/except.c +2 -0
  15. data/ext/except.h +25 -23
  16. data/ext/extconf.rb +1 -0
  17. data/ext/ferret.c +10 -8
  18. data/ext/ferret.h +9 -8
  19. data/ext/field.c +29 -25
  20. data/ext/filter.c +52 -14
  21. data/ext/frtio.h +13 -0
  22. data/ext/fs_store.c +115 -170
  23. data/ext/global.c +9 -8
  24. data/ext/global.h +17 -13
  25. data/ext/hash.c +13 -19
  26. data/ext/hash.h +11 -11
  27. data/ext/hashset.c +5 -7
  28. data/ext/hashset.h +9 -8
  29. data/ext/helper.c +1 -1
  30. data/ext/helper.h +2 -1
  31. data/ext/inc/except.h +25 -23
  32. data/ext/inc/lang.h +11 -1
  33. data/ext/ind.c +33 -21
  34. data/ext/index.h +44 -39
  35. data/ext/index_io.c +61 -57
  36. data/ext/index_rw.c +418 -361
  37. data/ext/lang.c +10 -0
  38. data/ext/lang.h +11 -1
  39. data/ext/nix_io.c +135 -0
  40. data/ext/priorityqueue.c +16 -16
  41. data/ext/priorityqueue.h +9 -6
  42. data/ext/q_boolean.c +128 -76
  43. data/ext/q_const_score.c +20 -20
  44. data/ext/q_filtered_query.c +20 -20
  45. data/ext/q_fuzzy.c +37 -23
  46. data/ext/q_match_all.c +15 -19
  47. data/ext/q_multi_phrase.c +87 -46
  48. data/ext/q_parser.c +247 -119
  49. data/ext/q_phrase.c +86 -52
  50. data/ext/q_prefix.c +25 -14
  51. data/ext/q_range.c +59 -14
  52. data/ext/q_span.c +263 -172
  53. data/ext/q_term.c +62 -51
  54. data/ext/q_wildcard.c +24 -13
  55. data/ext/r_analysis.c +328 -80
  56. data/ext/r_doc.c +11 -6
  57. data/ext/r_index_io.c +40 -32
  58. data/ext/r_qparser.c +15 -14
  59. data/ext/r_search.c +270 -152
  60. data/ext/r_store.c +32 -17
  61. data/ext/ram_store.c +38 -22
  62. data/ext/search.c +617 -87
  63. data/ext/search.h +227 -163
  64. data/ext/similarity.c +54 -45
  65. data/ext/similarity.h +3 -3
  66. data/ext/sort.c +132 -53
  67. data/ext/store.c +21 -2
  68. data/ext/store.h +14 -14
  69. data/ext/tags +4322 -232
  70. data/ext/term.c +140 -109
  71. data/ext/termdocs.c +74 -60
  72. data/ext/vector.c +181 -152
  73. data/ext/w32_io.c +150 -0
  74. data/lib/ferret.rb +1 -1
  75. data/lib/ferret/analysis/standard_tokenizer.rb +4 -3
  76. data/lib/ferret/document/field.rb +1 -1
  77. data/lib/ferret/index/field_infos.rb +1 -1
  78. data/lib/ferret/index/term.rb +1 -1
  79. data/lib/ferret/query_parser/query_parser.tab.rb +8 -24
  80. data/lib/ferret/search.rb +1 -0
  81. data/lib/ferret/search/boolean_query.rb +0 -4
  82. data/lib/ferret/search/index_searcher.rb +21 -8
  83. data/lib/ferret/search/multi_phrase_query.rb +7 -0
  84. data/lib/ferret/search/multi_searcher.rb +261 -0
  85. data/lib/ferret/search/phrase_query.rb +1 -1
  86. data/lib/ferret/search/query.rb +34 -5
  87. data/lib/ferret/search/sort.rb +7 -3
  88. data/lib/ferret/search/sort_field.rb +8 -4
  89. data/lib/ferret/store/fs_store.rb +13 -6
  90. data/lib/ferret/store/index_io.rb +0 -14
  91. data/lib/ferret/store/ram_store.rb +3 -2
  92. data/lib/rferret.rb +1 -1
  93. data/test/unit/analysis/ctc_analyzer.rb +131 -0
  94. data/test/unit/analysis/ctc_tokenstream.rb +98 -9
  95. data/test/unit/index/tc_index.rb +40 -1
  96. data/test/unit/index/tc_term.rb +7 -0
  97. data/test/unit/index/th_doc.rb +8 -0
  98. data/test/unit/query_parser/tc_query_parser.rb +6 -4
  99. data/test/unit/search/rtc_sort_field.rb +6 -6
  100. data/test/unit/search/tc_index_searcher.rb +8 -0
  101. data/test/unit/search/tc_multi_searcher.rb +275 -0
  102. data/test/unit/search/tc_multi_searcher2.rb +126 -0
  103. data/test/unit/search/tc_search_and_sort.rb +66 -0
  104. metadata +31 -26
  105. data/test/unit/query_parser/rtc_query_parser.rb +0 -138
data/ext/except.h CHANGED
@@ -7,7 +7,6 @@
7
7
  #define BODY 0
8
8
  #define FINALLY -1
9
9
  #define EXCEPTION 1
10
- #define ERROR 1
11
10
  #define IO_ERROR 2
12
11
  #define ARG_ERROR 3
13
12
  #define EOF_ERROR 4
@@ -29,35 +28,38 @@ RUBY_EXTERN int rb_thread_critical;
29
28
  extern xcontext_t *xtop_context;
30
29
 
31
30
  #define TRY\
32
- xcontext_t xcontext;\
33
- rb_thread_critical = Qtrue;\
34
- xcontext.next = xtop_context;\
35
- xtop_context = &xcontext;\
36
- xcontext.handled = true;\
37
- xcontext.in_finally = false;\
38
- switch (setjmp(xcontext.jbuf)) {\
39
- case BODY:
31
+ do {\
32
+ xcontext_t xcontext;\
33
+ rb_thread_critical = Qtrue;\
34
+ xcontext.next = xtop_context;\
35
+ xtop_context = &xcontext;\
36
+ xcontext.handled = true;\
37
+ xcontext.in_finally = false;\
38
+ switch (setjmp(xcontext.jbuf)) {\
39
+ case BODY:
40
40
 
41
41
 
42
42
  #define XENDTRY\
43
- }\
44
- xtop_context = xcontext.next;\
45
- if (!xcontext.handled) {\
46
- RAISE(xcontext.excode, xcontext.msg);\
47
- }\
48
- rb_thread_critical = 0;
49
-
50
- #define ENDTRY\
51
- }\
52
- if (!xcontext.in_finally) {\
43
+ }\
53
44
  xtop_context = xcontext.next;\
54
45
  if (!xcontext.handled) {\
55
46
  RAISE(xcontext.excode, xcontext.msg);\
56
47
  }\
57
- xcontext.in_finally = 1;\
58
- longjmp(xcontext.jbuf, FINALLY);\
59
- }\
60
- rb_thread_critical = 0;
48
+ rb_thread_critical = 0;\
49
+ } while (0);
50
+
51
+ #define ENDTRY\
52
+ }\
53
+ if (!xcontext.in_finally) {\
54
+ xtop_context = xcontext.next;\
55
+ if (!xcontext.handled) {\
56
+ RAISE(xcontext.excode, xcontext.msg);\
57
+ }\
58
+ xcontext.in_finally = 1;\
59
+ longjmp(xcontext.jbuf, FINALLY);\
60
+ }\
61
+ rb_thread_critical = 0;\
62
+ } while (0);
61
63
 
62
64
  #define XFINALLY default: xcontext.in_finally = 1;
63
65
 
data/ext/extconf.rb CHANGED
@@ -11,5 +11,6 @@ if (/mswin/ =~ RUBY_PLATFORM) and ENV['make'].nil?
11
11
  end
12
12
  else
13
13
  require 'mkmf'
14
+ $CFLAGS += " -fno-common"
14
15
  create_makefile("ferret_ext")
15
16
  end
data/ext/ferret.c CHANGED
@@ -7,6 +7,7 @@ static HshTable *object_map;
7
7
 
8
8
  /* IDs */
9
9
  ID id_new;
10
+ ID id_call;
10
11
 
11
12
  /* Modules */
12
13
  VALUE mFerret;
@@ -48,30 +49,30 @@ object_get(void *key)
48
49
  //static int hash_cnt = 0;
49
50
  void
50
51
  //object_add(void *key, VALUE obj)
51
- object_add2(void *key, VALUE obj, const char *file, int line, const char *func)
52
+ object_add2(void *key, VALUE obj, const char *file, int line)
52
53
  {
53
54
  if (h_get(object_map, key))
54
- printf("failed adding %d. %s:%d:%s\n", (int)key, file, line, func);
55
- //printf("adding %d. now contains %d %s:%d:%s\n", (int)key, ++hash_cnt, file, line, func);
55
+ printf("failed adding %d. %s:%d\n", (int)key, file, line);
56
+ //printf("adding %d. now contains %d %s:%d\n", (int)key, ++hash_cnt, file, line);
56
57
  h_set(object_map, key, (void *)obj);
57
58
  }
58
59
 
59
60
  void
60
61
  //object_set(void *key, VALUE obj)
61
- object_set2(void *key, VALUE obj, const char *file, int line, const char *func)
62
+ object_set2(void *key, VALUE obj, const char *file, int line)
62
63
  {
63
64
  //if (!h_get(object_map, key))
64
- //printf("seting %d. now contains %d %s:%d:%s\n", (int)key, ++hash_cnt, file, line, func);
65
+ //printf("seting %d. now contains %d %s:%d\n", (int)key, ++hash_cnt, file, line);
65
66
  h_set(object_map, key, (void *)obj);
66
67
  }
67
68
 
68
69
  void
69
70
  //object_del(void *key)
70
- object_del2(void *key, const char *file, int line, const char *func)
71
+ object_del2(void *key, const char *file, int line)
71
72
  {
72
73
  if (object_get(key) == Qnil)
73
- printf("failed deleting %d. %s:%d:%s\n", (int)key, file, line, func);
74
- //printf("deleting %d. now contains %d, %s:%d:%s\n", (int)key, --hash_cnt, file, line, func);
74
+ printf("failed deleting %d. %s:%d\n", (int)key, file, line);
75
+ //printf("deleting %d. now contains %d, %s:%d\n", (int)key, --hash_cnt, file, line);
75
76
  h_del(object_map, key);
76
77
  }
77
78
 
@@ -136,6 +137,7 @@ Init_ferret_ext(void)
136
137
 
137
138
  /* IDs */
138
139
  id_new = rb_intern("new");
140
+ id_call = rb_intern("call");
139
141
 
140
142
  /* Modules */
141
143
  mFerret = rb_define_module("Ferret");
data/ext/ferret.h CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  /* IDs */
8
8
  extern ID id_new;
9
+ extern ID id_call;
9
10
 
10
11
  /* Modules */
11
12
  extern VALUE mFerret;
@@ -30,14 +31,14 @@ extern void Init_index_io();
30
31
  extern void Init_search();
31
32
  extern void Init_qparser();
32
33
  //extern void object_add(void *key, VALUE obj);
33
- #define object_add(key, obj) object_add2(key, obj, __FILE__, __LINE__, __func__)
34
- extern void object_add2(void *key, VALUE obj, const char *file, int line, const char *func);
34
+ #define object_add(key, obj) object_add2(key, obj, __FILE__, __LINE__)
35
+ extern void object_add2(void *key, VALUE obj, const char *file, int line);
35
36
  //extern void object_set(void *key, VALUE obj);
36
- #define object_set(key, obj) object_set2(key, obj, __FILE__, __LINE__, __func__)
37
- extern void object_set2(void *key, VALUE obj, const char *file, int line, const char *func);
37
+ #define object_set(key, obj) object_set2(key, obj, __FILE__, __LINE__)
38
+ extern void object_set2(void *key, VALUE obj, const char *file, int line);
38
39
  //extern void object_del(void *key);
39
- #define object_del(key) object_del2(key, __FILE__, __LINE__, __func__)
40
- extern void object_del2(void *key, const char *file, int line, const char *func);
40
+ #define object_del(key) object_del2(key, __FILE__, __LINE__)
41
+ extern void object_del2(void *key, const char *file, int line);
41
42
  extern void frt_gc_mark(void *key);
42
43
  extern VALUE object_get(void *key);
43
44
  extern VALUE frt_data_alloc(VALUE klass);
@@ -51,8 +52,8 @@ extern void frt_deref_free(void *p);
51
52
  #define Frt_Wrap_Struct(self,mmark,mfree,mdata)\
52
53
  do {\
53
54
  ((struct RData *)(self))->data = mdata;\
54
- ((struct RData *)(self))->dmark = mmark;\
55
- ((struct RData *)(self))->dfree = mfree;\
55
+ ((struct RData *)(self))->dmark = (RUBY_DATA_FUNC)mmark;\
56
+ ((struct RData *)(self))->dfree = (RUBY_DATA_FUNC)mfree;\
56
57
  } while (0)
57
58
 
58
59
  #define Frt_Unwrap_Struct(self)\
data/ext/field.c CHANGED
@@ -1,4 +1,4 @@
1
- #include <index.h>
1
+ #include "index.h"
2
2
  #include <string.h>
3
3
 
4
4
  /****************************************************************************
@@ -21,9 +21,8 @@ FieldInfo *fi_create(char *name, int number, bool is_indexed,
21
21
  return fi;
22
22
  }
23
23
 
24
- void fi_destroy(void *p)
24
+ void fi_destroy(FieldInfo *fi)
25
25
  {
26
- FieldInfo *fi = (FieldInfo *)p;
27
26
  free(fi->name);
28
27
  free(fi);
29
28
  }
@@ -55,10 +54,9 @@ FieldInfos *fis_open(Store *store, char *filename)
55
54
  return fis;
56
55
  }
57
56
 
58
- void fis_destroy(void *p)
57
+ void fis_destroy(FieldInfos *fis)
59
58
  {
60
59
  int i;
61
- FieldInfos *fis = (FieldInfos *)p;
62
60
  for (i = 0; i < fis->fcnt; i++) {
63
61
  fi_destroy(fis->by_number[i]);
64
62
  }
@@ -130,11 +128,11 @@ FieldInfo *fis_get_fi(FieldInfos *fis, char *name)
130
128
  return (FieldInfo *)ht_get(fis->by_name, name);
131
129
  }
132
130
 
133
- unsigned long long fis_get_number(FieldInfos *fis, char *name)
131
+ ullong fis_get_number(FieldInfos *fis, char *name)
134
132
  {
135
133
  FieldInfo *fi = (FieldInfo *)ht_get(fis->by_name, name);
136
134
  if (fi == NULL)
137
- return 0xFFFFFFFFull; // to be compatible with Jave version
135
+ return NOT_A_FIELD;
138
136
  else
139
137
  return fi->number;
140
138
  }
@@ -166,9 +164,11 @@ void fis_write(FieldInfos *fis, Store *store, char *segment, char *ext)
166
164
  int i;
167
165
  FieldInfo *fi;
168
166
  char fname[SEGMENT_NAME_MAX_LENGTH];
167
+ OutStream *os;
168
+
169
169
  strcpy(fname, segment);
170
170
  strcat(fname, ext);
171
- OutStream *os = store->create_output(store, fname);
171
+ os = store->create_output(store, fname);
172
172
  TRY
173
173
  os_write_vint(os, fis->fcnt);
174
174
  for (i = 0; i < fis->fcnt; i++) {
@@ -183,7 +183,7 @@ void fis_write(FieldInfos *fis, Store *store, char *segment, char *ext)
183
183
 
184
184
  FieldInfos *fis_read(FieldInfos *fis, InStream *is)
185
185
  {
186
- int i, size = is_read_vint(is); //read in the size
186
+ int i, size = (int)is_read_vint(is); /* read in the size */
187
187
  int bits, is_indexed, store_tv, store_pos, store_offset, omit_norms;
188
188
  char *name;
189
189
  for (i = 0; i < size; i++) {
@@ -221,11 +221,12 @@ FieldInfos *fis_add_doc(FieldInfos *fis, Document *doc)
221
221
 
222
222
  FieldsWriter *fw_open(Store *store, char *segment, FieldInfos *fis)
223
223
  {
224
+ FieldsWriter *fw = ALLOC(FieldsWriter);
224
225
  char buf[SEGMENT_NAME_MAX_LENGTH];
225
- int slen = strlen(segment);
226
+ int slen = (int)strlen(segment);
227
+
226
228
  strcpy(buf, segment);
227
229
 
228
- FieldsWriter *fw = ALLOC(FieldsWriter);
229
230
  fw->fis = fis;
230
231
  strcpy(buf+slen, ".fdt");
231
232
  fw->fields_out = store->create_output(store, buf);
@@ -250,12 +251,13 @@ void save_data(OutStream *fout, char *data, int dlen)
250
251
  void fw_add_doc(FieldsWriter *fw, Document *doc)
251
252
  {
252
253
  int i, bits;
253
- OutStream *fout = fw->fields_out, *iout = fw->index_out;
254
- os_write_long(iout, os_pos(fout));
255
254
  DocField *df;
256
255
  char *data;
257
-
258
256
  int stored_count = 0;
257
+ OutStream *fout = fw->fields_out, *iout = fw->index_out;
258
+
259
+ os_write_long(iout, os_pos(fout));
260
+
259
261
  for (i = 0; i < doc->dfcnt; i++) {
260
262
  if (doc->df_arr[i]->is_stored)
261
263
  stored_count++;
@@ -303,16 +305,17 @@ void fw_add_doc(FieldsWriter *fw, Document *doc)
303
305
 
304
306
  FieldsReader *fr_open(Store *store, char *segment, FieldInfos *fis)
305
307
  {
308
+ FieldsReader *fr = ALLOC(FieldsReader);
309
+ InStream *iin;
306
310
  char buf[100];
307
- int slen = strlen(segment);
311
+ int slen = (int)strlen(segment);
308
312
  strcpy(buf, segment);
309
313
 
310
- FieldsReader *fr = ALLOC(FieldsReader);
311
314
  fr->fis = fis;
312
315
  strcpy(buf+slen, ".fdt");
313
316
  fr->fields_in = store->open_input(store, buf);
314
317
  strcpy(buf+slen, ".fdx");
315
- InStream *iin = fr->index_in = store->open_input(store, buf);
318
+ iin = fr->index_in = store->open_input(store, buf);
316
319
  fr->len = iin->length_internal(iin)/8;
317
320
  return fr;
318
321
  }
@@ -327,21 +330,22 @@ void fr_close(FieldsReader *fr)
327
330
  Document *fr_get_doc(FieldsReader *fr, int doc_num)
328
331
  {
329
332
  int i, bits, dlen;
333
+ FieldInfo *fi;
330
334
  char *data;
331
335
  int store, index, stv;
332
336
  int is_compressed, is_tokenized, is_binary;
337
+ int position, field_cnt, field_number;
333
338
  Document *doc = doc_create();
334
339
  InStream *iin = fr->index_in;
335
340
  InStream *fin = fr->fields_in;
341
+
336
342
  is_seek(iin, doc_num * 8);
337
- int position = is_read_long(iin);
343
+ position = (int)is_read_long(iin);
338
344
  is_seek(fin, position);
339
- int field_cnt = is_read_vint(fin);
340
- int field_number;
341
- FieldInfo *fi;
342
-
345
+ field_cnt = (int)is_read_vint(fin);
346
+
343
347
  for (i = 0; i < field_cnt; i++) {
344
- field_number = is_read_vint(fin);
348
+ field_number = (int)is_read_vint(fin);
345
349
  fi = fr->fis->by_number[field_number];
346
350
 
347
351
  bits = is_read_byte(fin);
@@ -351,7 +355,7 @@ Document *fr_get_doc(FieldsReader *fr, int doc_num)
351
355
  is_binary = (bits & FIELD_IS_BINARY) != 0;
352
356
 
353
357
  if (is_binary) {
354
- dlen = is_read_vint(fin);
358
+ dlen = (int)is_read_vint(fin);
355
359
  data = ALLOC_N(char, dlen);
356
360
  is_read_bytes(fin, (uchar *)data, 0, dlen);
357
361
  if (is_compressed) {
@@ -373,7 +377,7 @@ Document *fr_get_doc(FieldsReader *fr, int doc_num)
373
377
  data = NULL;
374
378
  if (is_compressed) {
375
379
  store = DF_STORE_COMPRESS;
376
- dlen = is_read_vint(fin);
380
+ dlen = (int)is_read_vint(fin);
377
381
  data = ALLOC_N(char, (dlen + 1));
378
382
  data[dlen] = '\0';
379
383
  is_read_bytes(fin, (uchar *)data, 0, dlen);
data/ext/filter.c CHANGED
@@ -1,5 +1,5 @@
1
- #include <string.h>
2
1
  #include "search.h"
2
+ #include <string.h>
3
3
 
4
4
  /***************************************************************************
5
5
  *
@@ -7,9 +7,8 @@
7
7
  *
8
8
  ***************************************************************************/
9
9
 
10
- void filt_destroy(void *p)
10
+ void filt_destroy(Filter *self)
11
11
  {
12
- Filter *self = (Filter *)p;
13
12
  h_destroy(self->cache);
14
13
  free(self->name);
15
14
  free(self);
@@ -25,26 +24,51 @@ BitVector *filt_get_bv(Filter *self, IndexReader *ir)
25
24
  }
26
25
  bv = self->get_bv(self, ir);
27
26
  co = co_create(self->cache, ir->cache, self, ir,
28
- &bv_destroy, (void *)bv);
27
+ (free_ft)&bv_destroy, (void *)bv);
29
28
  }
30
29
  return (BitVector *)co->obj;
31
30
  }
32
31
 
33
- char *filt_to_s(Filter *self)
32
+ char *filt_to_s_i(Filter *self)
34
33
  {
35
34
  return estrdup(self->name);
36
35
  }
37
36
 
37
+ uint filt_hash_dflt(Filter *self)
38
+ {
39
+ return 0;
40
+ }
41
+
42
+ int filt_eq_dflt(Filter *self, Filter *o)
43
+ {
44
+ return false;
45
+ }
46
+
38
47
  Filter *filt_create(char *name)
39
48
  {
40
49
  Filter *self = ALLOC(Filter);
41
50
  self->cache = co_hsh_create();
42
51
  self->name = estrdup(name);
43
- self->to_s = &filt_to_s;
52
+ self->to_s = &filt_to_s_i;
53
+ self->hash = &filt_hash_dflt;
54
+ self->eq = &filt_eq_dflt;
44
55
  self->destroy = &filt_destroy;
45
56
  return self;
46
57
  }
47
58
 
59
+ uint filt_hash(Filter *self)
60
+ {
61
+ return str_hash(self->name) ^ self->hash(self);
62
+ }
63
+
64
+ int filt_eq(Filter *self, Filter *o)
65
+ {
66
+ return ((self == o) ||
67
+ ((strcmp(self->name, o->name) == 0) &&
68
+ (self->eq == o->eq) &&
69
+ (self->eq(self, o))));
70
+ }
71
+
48
72
  /***************************************************************************
49
73
  *
50
74
  * QueryFilter
@@ -56,7 +80,7 @@ char *qfilt_to_s(Filter *self)
56
80
  QueryFilter *qf = (QueryFilter *)self->data;
57
81
  Query *query = (Query *)qf->query;
58
82
  char *query_str = query->to_s(query, "");
59
- char *filter_str = strfmt("QueryFilter(%s)", query_str);
83
+ char *filter_str = strfmt("QueryFilter< %s >", query_str);
60
84
  free(query_str);
61
85
  return filter_str;
62
86
  }
@@ -74,18 +98,30 @@ BitVector *qfilt_get_bv(Filter *filt, IndexReader *ir)
74
98
  }
75
99
  scorer->destroy(scorer);
76
100
  }
101
+ weight->destroy(weight);
77
102
  free(sea);
78
103
  return bv;
79
104
  }
80
105
 
81
- void qfilt_destroy(void *p)
106
+ uint qfilt_hash(Filter *self)
107
+ {
108
+ Query *query = (Query *)((QueryFilter *)self->data)->query;
109
+ return q_hash(query);
110
+ }
111
+
112
+ int qfilt_eq(Filter *self, Filter *o)
113
+ {
114
+ Query *query1 = (Query *)((QueryFilter *)self->data)->query;
115
+ Query *query2 = (Query *)((QueryFilter *)o->data)->query;
116
+ return q_eq(query1, query2);
117
+ }
118
+
119
+ void qfilt_destroy(Filter *self)
82
120
  {
83
- Filter *filt = (Filter *)p;
84
- QueryFilter *qfilt = filt->data;
85
- /* caller is responsible for closing the query */
86
- /* if (qfilt->query) qfilt->query->destroy(qfilt->query); */
87
- free(qfilt);
88
- filt_destroy(filt);
121
+ Query *query = (Query *)((QueryFilter *)self->data)->query;
122
+ q_deref(query);
123
+ free(self->data);
124
+ filt_destroy(self);
89
125
  }
90
126
 
91
127
  Filter *qfilt_create(Query *query)
@@ -97,6 +133,8 @@ Filter *qfilt_create(Query *query)
97
133
  self = filt_create("QueryFilter");
98
134
  self->data = qfilt;
99
135
  self->get_bv = &qfilt_get_bv;
136
+ self->hash = &qfilt_hash;
137
+ self->eq = &qfilt_eq;
100
138
  self->to_s = &qfilt_to_s;
101
139
  self->destroy = &qfilt_destroy;
102
140
  return self;