ferret 0.10.13 → 0.10.14

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -41,7 +41,7 @@ SRC = (FileList["ext/*.[ch]"] + EXT_SRC_DEST).uniq
41
41
 
42
42
  CLEAN.include(FileList['**/*.o', '**/*.obj', 'InstalledFiles',
43
43
  '.config', 'ext/cferret.c'])
44
- CLOBBER.include(FileList['**/*.so'], 'ext/Makefile', 'ext/mem_pool.*', 'ext/defines.h', EXT_SRC_DEST)
44
+ CLOBBER.include(FileList['**/*.so'], 'ext/Makefile', EXT_SRC_DEST)
45
45
  POLISH = Rake::FileList.new.include(FileList['**/*.so'], 'ext/Makefile')
46
46
 
47
47
  desc "Clean specifically for the release."
@@ -115,7 +115,10 @@ EXT_SRC.each do |fn|
115
115
  end if File.exists?("../c")
116
116
 
117
117
  desc "Build the extension"
118
- task :ext => ["ext/#{EXT}"] + SRC
118
+ task :ext => ["ext/#{EXT}"] + SRC do
119
+ rm_f 'ext/mem_pool.*'
120
+ rm_f 'ext/defines.h'
121
+ end
119
122
 
120
123
  file "ext/#{EXT}" => ["ext/Makefile"] do
121
124
  cp "ext/inc/lang.h", "ext/lang.h"
data/ext/index.c CHANGED
@@ -91,7 +91,7 @@ HashTable *co_hash_create()
91
91
  *
92
92
  ****************************************************************************/
93
93
 
94
- __inline void fi_set_store(FieldInfo *fi, int store)
94
+ __inline void fi_set_store(FieldInfo *fi, int store)
95
95
  {
96
96
  switch (store) {
97
97
  case STORE_NO:
data/ext/q_phrase.c CHANGED
@@ -898,7 +898,12 @@ static char *phq_to_s(Query *self, const char *field)
898
898
  char *buffer;
899
899
 
900
900
  if (phq->pos_cnt == 0) {
901
- return NULL;
901
+ if (strcmp(field, phq->field) != 0) {
902
+ return strfmt("%s:\"\"", phq->field);
903
+ }
904
+ else {
905
+ return estrdup("\"\"");
906
+ }
902
907
  }
903
908
 
904
909
  /* sort the phrase positions by position */
data/ext/q_span.c CHANGED
@@ -439,6 +439,208 @@ static SpanEnum *spante_new(Query *query, IndexReader *ir)
439
439
  return self;
440
440
  }
441
441
 
442
+ /*****************************************************************************
443
+ * SpanMultiTermEnum
444
+ *****************************************************************************/
445
+
446
+ /* * TermPosEnumWrapper * */
447
+ #define TPE_READ_SIZE 16
448
+
449
+ typedef struct TermPosEnumWrapper
450
+ {
451
+ const char *term;
452
+ TermDocEnum *tpe;
453
+ int doc;
454
+ int pos;
455
+ } TermPosEnumWrapper;
456
+
457
+ static bool tpew_less_than(const TermPosEnumWrapper *tpew1,
458
+ const TermPosEnumWrapper *tpew2)
459
+ {
460
+ return (tpew1->doc < tpew2->doc)
461
+ || (tpew1->doc == tpew2->doc && tpew1->pos < tpew2->pos);
462
+ }
463
+
464
+ static bool tpew_next(TermPosEnumWrapper *self)
465
+ {
466
+ TermDocEnum *tpe = self->tpe;
467
+ if (0 > (self->pos = tpe->next_position(tpe))) {
468
+ if (!tpe->next(tpe)) return false;
469
+ self->doc = tpe->doc_num(tpe);
470
+ self->pos = tpe->next_position(tpe);
471
+ }
472
+ return true;
473
+ }
474
+
475
+ static bool tpew_skip_to(TermPosEnumWrapper *self, int doc_num)
476
+ {
477
+ TermDocEnum *tpe = self->tpe;
478
+
479
+ if (tpe->skip_to(tpe, doc_num)) {
480
+ self->doc = tpe->doc_num(tpe);
481
+ self->pos = tpe->next_position(tpe);
482
+ return true;
483
+ }
484
+ else {
485
+ return false;
486
+ }
487
+ }
488
+
489
+ static void tpew_destroy(TermPosEnumWrapper *self)
490
+ {
491
+ self->tpe->close(self->tpe);
492
+ free(self);
493
+ }
494
+
495
+ static TermPosEnumWrapper *tpew_new(const char *term, TermDocEnum *tpe)
496
+ {
497
+ TermPosEnumWrapper *self = ALLOC_AND_ZERO(TermPosEnumWrapper);
498
+ self->term = term;
499
+ self->tpe = tpe;
500
+ self->doc = -1;
501
+ self->pos = -1;
502
+ return self;
503
+ }
504
+ #define SpMTEn(span_enum) ((SpanMultiTermEnum *)(span_enum))
505
+ #define SpMTQ(query) ((SpanMultiTermQuery *)(query))
506
+
507
+ typedef struct SpanMultiTermEnum
508
+ {
509
+ SpanEnum super;
510
+ PriorityQueue *tpew_pq;
511
+ TermPosEnumWrapper **tpews;
512
+ int tpew_cnt;
513
+ int pos;
514
+ int doc;
515
+ } SpanMultiTermEnum;
516
+
517
+ static bool spanmte_next(SpanEnum *self)
518
+ {
519
+ int curr_doc, curr_pos;
520
+ TermPosEnumWrapper *tpew;
521
+ SpanMultiTermEnum *mte = SpMTEn(self);
522
+ PriorityQueue *tpew_pq = mte->tpew_pq;
523
+ if (tpew_pq == NULL) {
524
+ TermPosEnumWrapper **tpews = mte->tpews;
525
+ int i;
526
+ tpew_pq = pq_new(mte->tpew_cnt, (lt_ft)tpew_less_than, (free_ft)NULL);
527
+ for (i = mte->tpew_cnt - 1; i >= 0; i--) {
528
+ if (tpew_next(tpews[i])) {
529
+ pq_push(tpew_pq, tpews[i]);
530
+ }
531
+ }
532
+ mte->tpew_pq = tpew_pq;
533
+ }
534
+
535
+ tpew = (TermPosEnumWrapper *)pq_top(tpew_pq);
536
+ if (tpew == NULL) {
537
+ return false;
538
+ }
539
+
540
+ mte->doc = curr_doc = tpew->doc;
541
+ mte->pos = curr_pos = tpew->pos;
542
+
543
+ do {
544
+ if (tpew_next(tpew)) {
545
+ pq_down(tpew_pq);
546
+ }
547
+ else {
548
+ pq_pop(tpew_pq);
549
+ }
550
+ } while (((tpew = (TermPosEnumWrapper *)pq_top(tpew_pq)) != NULL)
551
+ && tpew->doc == curr_doc && tpew->pos == curr_pos);
552
+ return true;
553
+ }
554
+
555
+ static bool spanmte_skip_to(SpanEnum *self, int target)
556
+ {
557
+ SpanMultiTermEnum *mte = SpMTEn(self);
558
+ PriorityQueue *tpew_pq = mte->tpew_pq;
559
+ TermPosEnumWrapper *tpew;
560
+ if (tpew_pq == NULL) {
561
+ TermPosEnumWrapper **tpews = mte->tpews;
562
+ int i;
563
+ tpew_pq = pq_new(mte->tpew_cnt, (lt_ft)tpew_less_than, (free_ft)NULL);
564
+ for (i = mte->tpew_cnt - 1; i >= 0; i--) {
565
+ tpew_skip_to(tpews[i], target);
566
+ pq_push(tpew_pq, tpews[i]);
567
+ }
568
+ mte->tpew_pq = tpew_pq;
569
+ }
570
+ if (tpew_pq->size == 0) {
571
+ mte->doc = -1;
572
+ return false;
573
+ }
574
+ while ((tpew = (TermPosEnumWrapper *)pq_top(tpew_pq)) != NULL
575
+ && (target > tpew->doc)) {
576
+ if (tpew_skip_to(tpew, target)) {
577
+ pq_down(tpew_pq);
578
+ }
579
+ else {
580
+ pq_pop(tpew_pq);
581
+ }
582
+ }
583
+ return spanmte_next(self);
584
+ }
585
+
586
+ static int spanmte_doc(SpanEnum *self)
587
+ {
588
+ return SpMTEn(self)->doc;
589
+ }
590
+
591
+ static int spanmte_start(SpanEnum *self)
592
+ {
593
+ return SpMTEn(self)->pos;
594
+ }
595
+
596
+ static int spanmte_end(SpanEnum *self)
597
+ {
598
+ return SpMTEn(self)->pos + 1;
599
+ }
600
+
601
+ static void spanmte_destroy(SpanEnum *self)
602
+ {
603
+ SpanMultiTermEnum *mte = SpMTEn(self);
604
+ int i;
605
+ if (mte->tpew_pq) pq_destroy(mte->tpew_pq);
606
+ for (i = 0; i < mte->tpew_cnt; i++) {
607
+ tpew_destroy(mte->tpews[i]);
608
+ }
609
+ free(mte->tpews);
610
+ free(self);
611
+ }
612
+
613
+ static SpanEnum *spanmte_new(Query *query, IndexReader *ir)
614
+ {
615
+ char *field = SpQ(query)->field;
616
+ SpanEnum *self = (SpanEnum *)emalloc(sizeof(SpanMultiTermEnum));
617
+ SpanMultiTermEnum *smte = SpMTEn(self);
618
+ SpanMultiTermQuery *smtq = SpMTQ(query);
619
+ int i;
620
+
621
+
622
+ smte->tpews = ALLOC_N(TermPosEnumWrapper *, smtq->term_cnt);
623
+ for (i = 0; i < smtq->term_cnt; i++) {
624
+ char *term = smtq->terms[i];
625
+ smte->tpews[i] = tpew_new(term, ir_term_positions_for(ir, field, term));
626
+ }
627
+ smte->tpew_cnt = smtq->term_cnt;
628
+ smte->tpew_pq = NULL;
629
+ smte->pos = -1;
630
+ smte->doc = -1;
631
+
632
+ self->query = query;
633
+ self->next = &spanmte_next;
634
+ self->skip_to = &spanmte_skip_to;
635
+ self->doc = &spanmte_doc;
636
+ self->start = &spanmte_start;
637
+ self->end = &spanmte_end;
638
+ self->destroy = &spanmte_destroy;
639
+ self->to_s = &spante_to_s;
640
+
641
+ return self;
642
+ }
643
+
442
644
 
443
645
  /*****************************************************************************
444
646
  * SpanFirstEnum
@@ -1385,6 +1587,132 @@ Query *spantq_new(const char *field, const char *term)
1385
1587
  return self;
1386
1588
  }
1387
1589
 
1590
+ /*****************************************************************************
1591
+ * SpanMultiTermQuery
1592
+ *****************************************************************************/
1593
+
1594
+ static char *spanmtq_to_s(Query *self, const char *field)
1595
+ {
1596
+ char *terms = NULL, *p;
1597
+ int len = 2, i;
1598
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1599
+ for (i = 0; i < smtq->term_cnt; i++) {
1600
+ len += strlen(smtq->terms[i]) + 2;
1601
+ }
1602
+ p = terms = ALLOC_N(char, len);
1603
+ *(p++) = '[';
1604
+ for (i = 0; i < smtq->term_cnt; i++) {
1605
+ strcpy(p, smtq->terms[i]);
1606
+ p += strlen(smtq->terms[i]);
1607
+ *(p++) = ',';
1608
+ }
1609
+ if (p > terms) p--;
1610
+ *(p++) = ']';
1611
+ *p = '\0';
1612
+
1613
+ if (field == SpQ(self)->field) {
1614
+ p = strfmt("span_terms(%s)", terms);
1615
+ }
1616
+ else {
1617
+ p = strfmt("span_terms(%s:%s)", SpQ(self)->field, terms);
1618
+ }
1619
+ free(terms);
1620
+ return p;
1621
+ }
1622
+
1623
+ static void spanmtq_destroy_i(Query *self)
1624
+ {
1625
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1626
+ int i;
1627
+ for (i = 0; i < smtq->term_cnt; i++) {
1628
+ free(smtq->terms[i]);
1629
+ }
1630
+ free(smtq->terms);
1631
+ free(SpQ(self)->field);
1632
+ spanq_destroy_i(self);
1633
+ }
1634
+
1635
+ static void spanmtq_extract_terms(Query *self, HashSet *terms)
1636
+ {
1637
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1638
+ int i;
1639
+ for (i = 0; i < smtq->term_cnt; i++) {
1640
+ hs_add(terms, term_new(SpQ(self)->field, smtq->terms[i]));
1641
+ }
1642
+ }
1643
+
1644
+ static HashSet *spanmtq_get_terms(Query *self)
1645
+ {
1646
+ HashSet *terms = hs_new_str(&free);
1647
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1648
+ int i;
1649
+ for (i = 0; i < smtq->term_cnt; i++) {
1650
+ hs_add(terms, estrdup(smtq->terms[i]));
1651
+ }
1652
+ return terms;
1653
+ }
1654
+
1655
+ static unsigned long spanmtq_hash(Query *self)
1656
+ {
1657
+ unsigned long hash = spanq_hash(self);
1658
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1659
+ int i;
1660
+ for (i = 0; i < smtq->term_cnt; i++) {
1661
+ hash ^= str_hash(smtq->terms[i]);
1662
+ }
1663
+ return hash;
1664
+ }
1665
+
1666
+ static int spanmtq_eq(Query *self, Query *o)
1667
+ {
1668
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1669
+ SpanMultiTermQuery *smtqo = SpMTQ(o);
1670
+ int i;
1671
+ if (!spanq_eq(self, o)) return false;
1672
+ if (smtq->term_cnt != smtqo->term_cnt) return false;
1673
+ for (i = 0; i < smtq->term_cnt; i++) {
1674
+ if (strcmp(smtq->terms[i], smtqo->terms[i]) != 0) return false;
1675
+ }
1676
+ return true;;
1677
+ }
1678
+
1679
+ Query *spanmtq_new_conf(const char *field, int max_terms)
1680
+ {
1681
+ Query *self = q_new(SpanMultiTermQuery);
1682
+
1683
+ SpMTQ(self)->terms = ALLOC_N(char *, max_terms);
1684
+ SpMTQ(self)->term_cnt = 0;
1685
+ SpMTQ(self)->term_capa = max_terms;
1686
+
1687
+ SpQ(self)->field = estrdup(field);
1688
+ SpQ(self)->get_spans = &spanmte_new;
1689
+ SpQ(self)->get_terms = &spanmtq_get_terms;
1690
+
1691
+ self->type = SPAN_MULTI_TERM_QUERY;
1692
+ self->extract_terms = &spanmtq_extract_terms;
1693
+ self->to_s = &spanmtq_to_s;
1694
+ self->hash = &spanmtq_hash;
1695
+ self->eq = &spanmtq_eq;
1696
+ self->destroy_i = &spanmtq_destroy_i;
1697
+ self->create_weight_i = &spanw_new;
1698
+ self->get_matchv_i = &spanq_get_matchv_i;
1699
+
1700
+ return self;
1701
+ }
1702
+
1703
+ Query *spanmtq_new(const char *field)
1704
+ {
1705
+ return spanmtq_new_conf(field, SPAN_MULTI_TERM_QUERY_CAPA);
1706
+ }
1707
+
1708
+ void spanmtq_add_term(Query *self, const char *term)
1709
+ {
1710
+ SpanMultiTermQuery *smtq = SpMTQ(self);
1711
+ if (smtq->term_cnt < smtq->term_capa) {
1712
+ smtq->terms[smtq->term_cnt++] = estrdup(term);
1713
+ }
1714
+ }
1715
+
1388
1716
  /*****************************************************************************
1389
1717
  *
1390
1718
  * SpanFirstQuery
@@ -1427,6 +1755,7 @@ static Query *spanfq_rewrite(Query *self, IndexReader *ir)
1427
1755
  static void spanfq_destroy_i(Query *self)
1428
1756
  {
1429
1757
  q_deref(SpFQ(self)->match);
1758
+ free(SpQ(self)->field);
1430
1759
  spanq_destroy_i(self);
1431
1760
  }
1432
1761
 
@@ -1451,7 +1780,7 @@ Query *spanfq_new_nr(Query *match, int end)
1451
1780
  SpFQ(self)->match = match;
1452
1781
  SpFQ(self)->end = end;
1453
1782
 
1454
- SpQ(self)->field = SpQ(match)->field;
1783
+ SpQ(self)->field = estrdup(SpQ(match)->field);
1455
1784
  SpQ(self)->get_spans = &spanfe_new;
1456
1785
  SpQ(self)->get_terms = &spanfq_get_terms;
1457
1786
 
@@ -1569,6 +1898,7 @@ static void spanoq_destroy_i(Query *self)
1569
1898
  q_deref(clause);
1570
1899
  }
1571
1900
  free(soq->clauses);
1901
+ free(SpQ(self)->field);
1572
1902
 
1573
1903
  spanq_destroy_i(self);
1574
1904
  }
@@ -1612,7 +1942,7 @@ Query *spanoq_new()
1612
1942
  SpOQ(self)->clauses = ALLOC_N(Query *, CLAUSE_INIT_CAPA);
1613
1943
  SpOQ(self)->c_capa = CLAUSE_INIT_CAPA;
1614
1944
 
1615
- SpQ(self)->field = (char *)EMPTY_STRING;
1945
+ SpQ(self)->field = estrdup((char *)EMPTY_STRING);
1616
1946
  SpQ(self)->get_spans = &spanoq_get_spans;
1617
1947
  SpQ(self)->get_terms = &spanoq_get_terms;
1618
1948
 
@@ -1637,7 +1967,8 @@ Query *spanoq_add_clause_nr(Query *self, Query *clause)
1637
1967
  "SpanQuery.", q_get_query_name(clause->type));
1638
1968
  }
1639
1969
  if (curr_index == 0) {
1640
- SpQ(self)->field = SpQ(clause)->field;
1970
+ free(SpQ(self)->field);
1971
+ SpQ(self)->field = estrdup(SpQ(clause)->field);
1641
1972
  }
1642
1973
  else if (strcmp(SpQ(self)->field, SpQ(clause)->field) != 0) {
1643
1974
  RAISE(ARG_ERROR, "All clauses in a SpanQuery must have the same field. "
@@ -1752,6 +2083,7 @@ static void spannq_destroy(Query *self)
1752
2083
  q_deref(clause);
1753
2084
  }
1754
2085
  free(snq->clauses);
2086
+ free(SpQ(self)->field);
1755
2087
 
1756
2088
  spanq_destroy_i(self);
1757
2089
  }
@@ -1804,7 +2136,7 @@ Query *spannq_new(int slop, bool in_order)
1804
2136
 
1805
2137
  SpQ(self)->get_spans = &spannq_get_spans;
1806
2138
  SpQ(self)->get_terms = &spannq_get_terms;
1807
- SpQ(self)->field = (char *)EMPTY_STRING;
2139
+ SpQ(self)->field = estrdup((char *)EMPTY_STRING);
1808
2140
 
1809
2141
  self->type = SPAN_NEAR_QUERY;
1810
2142
  self->rewrite = &spannq_rewrite;
@@ -1827,7 +2159,8 @@ Query *spannq_add_clause_nr(Query *self, Query *clause)
1827
2159
  "SpanQuery.", q_get_query_name(clause->type));
1828
2160
  }
1829
2161
  if (curr_index == 0) {
1830
- SpQ(self)->field = SpQ(clause)->field;
2162
+ free(SpQ(self)->field);
2163
+ SpQ(self)->field = estrdup(SpQ(clause)->field);
1831
2164
  }
1832
2165
  else if (strcmp(SpQ(self)->field, SpQ(clause)->field) != 0) {
1833
2166
  RAISE(ARG_ERROR, "All clauses in a SpanQuery must have the same field. "
@@ -1904,6 +2237,8 @@ static void spanxq_destroy(Query *self)
1904
2237
  q_deref(sxq->inc);
1905
2238
  q_deref(sxq->exc);
1906
2239
 
2240
+ free(SpQ(self)->field);
2241
+
1907
2242
  spanq_destroy_i(self);
1908
2243
  }
1909
2244
 
@@ -1937,7 +2272,7 @@ Query *spanxq_new_nr(Query *inc, Query *exc)
1937
2272
  SpXQ(self)->inc = inc;
1938
2273
  SpXQ(self)->exc = exc;
1939
2274
 
1940
- SpQ(self)->field = SpQ(inc)->field;
2275
+ SpQ(self)->field = estrdup(SpQ(inc)->field);
1941
2276
  SpQ(self)->get_spans = &spanxe_new;
1942
2277
  SpQ(self)->get_terms = &spanxq_get_terms;
1943
2278
 
@@ -1961,3 +2296,106 @@ Query *spanxq_new(Query *inc, Query *exc)
1961
2296
  return spanxq_new_nr(inc, exc);
1962
2297
  }
1963
2298
 
2299
+
2300
+ /*****************************************************************************
2301
+ *
2302
+ * Rewritables
2303
+ *
2304
+ *****************************************************************************/
2305
+
2306
+ /*****************************************************************************
2307
+ *
2308
+ * SpanPrefixQuery
2309
+ *
2310
+ *****************************************************************************/
2311
+
2312
+ #define SpPfxQ(query) ((SpanPrefixQuery *)(query))
2313
+
2314
+ static char *spanprq_to_s(Query *self, const char *current_field)
2315
+ {
2316
+ char *buffer, *bptr;
2317
+ const char *prefix = SpPfxQ(self)->prefix;
2318
+ const char *field = SpQ(self)->field;
2319
+ size_t plen = strlen(prefix);
2320
+ size_t flen = strlen(field);
2321
+
2322
+ bptr = buffer = ALLOC_N(char, plen + flen + 35);
2323
+
2324
+ if (strcmp(field, current_field) != 0) {
2325
+ sprintf(bptr, "%s:", field);
2326
+ bptr += flen + 1;
2327
+ }
2328
+
2329
+ sprintf(bptr, "%s*", prefix);
2330
+ bptr += plen + 1;
2331
+ if (self->boost != 1.0) {
2332
+ *bptr = '^';
2333
+ dbl_to_s(++bptr, self->boost);
2334
+ }
2335
+
2336
+ return buffer;
2337
+ }
2338
+
2339
+ static Query *spanprq_rewrite(Query *self, IndexReader *ir)
2340
+ {
2341
+ const char *field = SpQ(self)->field;
2342
+ const int field_num = fis_get_field_num(ir->fis, field);
2343
+ Query *volatile q = spanmtq_new_conf(field, SPAN_PREFIX_QUERY_MAX_TERMS);
2344
+ q->boost = self->boost; /* set the boost */
2345
+
2346
+ if (field_num >= 0) {
2347
+ const char *prefix = SpPfxQ(self)->prefix;
2348
+ TermEnum *te = ir->terms_from(ir, field_num, prefix);
2349
+ const char *term = te->curr_term;
2350
+ size_t prefix_len = strlen(prefix);
2351
+
2352
+ TRY
2353
+ do {
2354
+ if (strncmp(term, prefix, prefix_len) != 0) {
2355
+ break;
2356
+ }
2357
+ spanmtq_add_term(q, term); /* found a match */
2358
+ } while (te->next(te));
2359
+ XFINALLY
2360
+ te->close(te);
2361
+ XENDTRY
2362
+ }
2363
+
2364
+ return q;
2365
+ }
2366
+
2367
+ static void spanprq_destroy(Query *self)
2368
+ {
2369
+ free(SpQ(self)->field);
2370
+ free(SpPfxQ(self)->prefix);
2371
+ spanq_destroy_i(self);
2372
+ }
2373
+
2374
+ static unsigned long spanprq_hash(Query *self)
2375
+ {
2376
+ return str_hash(SpQ(self)->field) ^ str_hash(SpPfxQ(self)->prefix);
2377
+ }
2378
+
2379
+ static int spanprq_eq(Query *self, Query *o)
2380
+ {
2381
+ return (strcmp(SpPfxQ(self)->prefix, SpPfxQ(o)->prefix) == 0)
2382
+ && (strcmp(SpQ(self)->field, SpQ(o)->field) == 0);
2383
+ }
2384
+
2385
+ Query *spanprq_new(const char *field, const char *prefix)
2386
+ {
2387
+ Query *self = q_new(SpanPrefixQuery);
2388
+
2389
+ SpQ(self)->field = estrdup(field);
2390
+ SpPfxQ(self)->prefix = estrdup(prefix);
2391
+
2392
+ self->type = SPAN_PREFIX_QUERY;
2393
+ self->rewrite = &spanprq_rewrite;
2394
+ self->to_s = &spanprq_to_s;
2395
+ self->hash = &spanprq_hash;
2396
+ self->eq = &spanprq_eq;
2397
+ self->destroy_i = &spanprq_destroy;
2398
+ self->create_weight_i = &q_create_weight_unsup;
2399
+
2400
+ return self;
2401
+ }