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 +5 -2
- data/ext/index.c +1 -1
- data/ext/q_phrase.c +6 -1
- data/ext/q_span.c +444 -6
- data/ext/r_search.c +95 -1
- data/ext/search.c +2 -1
- data/ext/search.h +32 -1
- data/ext/sort.c +1 -1
- data/lib/ferret/index.rb +2 -0
- data/lib/ferret_version.rb +1 -1
- data/test/unit/analysis/tc_analyzer.rb +13 -13
- data/test/unit/analysis/tc_token_stream.rb +5 -5
- data/test/unit/search/tc_spans.rb +19 -3
- data/test/unit/search/tm_searcher.rb +7 -1
- metadata +123 -123
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',
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
+
}
|