ferret 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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;