15
15
#include " fts-flatcurve-config.h"
16
16
extern " C" {
17
17
#include " lib.h"
18
+ #include " array.h"
18
19
#include " file-create-locked.h"
19
20
#include " hash.h"
20
21
#include " mail-storage-private.h"
@@ -148,8 +149,17 @@ struct flatcurve_xapian {
148
149
bool closing:1 ;
149
150
};
150
151
152
+ struct flatcurve_fts_query_xapian_maybe {
153
+ Xapian::Query *query;
154
+ };
155
+
151
156
struct flatcurve_fts_query_xapian {
152
157
Xapian::Query *query;
158
+ ARRAY (struct flatcurve_fts_query_xapian_maybe ) maybe_queries;
159
+
160
+ bool and_search:1 ;
161
+ bool maybe:1 ;
162
+ bool start:1 ;
153
163
};
154
164
155
165
struct flatcurve_xapian_db_iter {
@@ -185,6 +195,7 @@ struct fts_flatcurve_xapian_query_iter {
185
195
Xapian::Enquire *enquire;
186
196
Xapian::MSetIterator i;
187
197
struct fts_flatcurve_xapian_query_result *result;
198
+ int curr_query;
188
199
};
189
200
190
201
static void
@@ -1465,19 +1476,22 @@ fts_flatcurve_build_query_arg_term(struct flatcurve_fts_query *query,
1465
1476
const char *term)
1466
1477
{
1467
1478
const char *hdr;
1479
+ bool maybe_or = FALSE ;
1480
+ struct flatcurve_fts_query_xapian_maybe *mquery;
1468
1481
Xapian::Query::op op = Xapian::Query::OP_INVALID;
1469
1482
Xapian::Query *oldq, q;
1470
1483
struct flatcurve_fts_query_xapian *x = query->xapian ;
1471
1484
1472
- if (x->query != NULL ) {
1473
- if ((query-> flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0 ) {
1485
+ if (x->start ) {
1486
+ if (x-> and_search ) {
1474
1487
op = Xapian::Query::OP_AND;
1475
1488
str_append (query->qtext , " AND " );
1476
1489
} else {
1477
1490
op = Xapian::Query::OP_OR;
1478
1491
str_append (query->qtext , " OR " );
1479
1492
}
1480
1493
}
1494
+ x->start = TRUE ;
1481
1495
1482
1496
if (arg->match_not )
1483
1497
str_append (query->qtext , " NOT " );
@@ -1529,7 +1543,10 @@ fts_flatcurve_build_query_arg_term(struct flatcurve_fts_query *query,
1529
1543
* appears in the general pool of header
1530
1544
* terms for the message, not to a specific
1531
1545
* header, so this is only a maybe match. */
1532
- query->maybe = TRUE ;
1546
+ if (x->and_search )
1547
+ x->maybe = TRUE ;
1548
+ else
1549
+ maybe_or = TRUE ;
1533
1550
}
1534
1551
} else {
1535
1552
hdr = t_str_lcase (arg->hdr_field_name );
@@ -1545,9 +1562,17 @@ fts_flatcurve_build_query_arg_term(struct flatcurve_fts_query *query,
1545
1562
q = Xapian::Query (Xapian::Query::OP_AND_NOT,
1546
1563
Xapian::Query::MatchAll, q);
1547
1564
1548
- if (x->query == NULL )
1565
+ if (maybe_or) {
1566
+ /* Maybe searches are not added to the "master search" query if this
1567
+ * is an OR search; they will be run independently. Matches will be
1568
+ * placed in the maybe results array. */
1569
+ if (!array_is_created (&x->maybe_queries ))
1570
+ p_array_init (&x->maybe_queries , query->pool , 4 );
1571
+ mquery = array_append_space (&x->maybe_queries );
1572
+ mquery->query = new Xapian::Query (std_move (q));
1573
+ } else if (x->query == NULL ) {
1549
1574
x->query = new Xapian::Query (std_move (q));
1550
- else {
1575
+ } else {
1551
1576
oldq = x->query ;
1552
1577
x->query = new Xapian::Query (op, *(x->query ), q);
1553
1578
delete (oldq);
@@ -1631,6 +1656,8 @@ void fts_flatcurve_xapian_build_query(struct flatcurve_fts_query *query)
1631
1656
return ;
1632
1657
}
1633
1658
1659
+ x->and_search = ((query->flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0 );
1660
+
1634
1661
for (; args != NULL ; args = args->next ) {
1635
1662
fts_flatcurve_build_query_arg (query, args);
1636
1663
}
@@ -1642,29 +1669,59 @@ fts_flatcurve_xapian_query_iter_init(struct flatcurve_fts_query *query)
1642
1669
struct fts_flatcurve_xapian_query_iter *iter;
1643
1670
1644
1671
iter = p_new (query->pool , struct fts_flatcurve_xapian_query_iter , 1 );
1672
+ /* -1: "Master" query
1673
+ * >= 0: Current index of maybe_queries */
1674
+ iter->curr_query = -1 ;
1645
1675
iter->query = query;
1646
1676
iter->result = p_new (query->pool ,
1647
1677
struct fts_flatcurve_xapian_query_result , 1 );
1648
1678
1649
1679
return iter;
1650
1680
}
1651
1681
1682
+ static void
1683
+ fts_flatcurve_xapian_query_iter_clear_current (struct fts_flatcurve_xapian_query_iter *iter)
1684
+ {
1685
+ iter->i .~MSetIterator ();
1686
+ delete (iter->enquire );
1687
+ iter->enquire = NULL ;
1688
+ }
1689
+
1652
1690
struct fts_flatcurve_xapian_query_result *
1653
1691
fts_flatcurve_xapian_query_iter_next (struct fts_flatcurve_xapian_query_iter *iter)
1654
1692
{
1655
1693
Xapian::MSet m;
1694
+ const struct flatcurve_fts_query_xapian_maybe *mquery;
1656
1695
enum flatcurve_xapian_db_opts opts =
1657
1696
ENUM_EMPTY (flatcurve_xapian_db_opts);
1697
+ Xapian::Query *q = NULL ;
1658
1698
1659
1699
if (iter->enquire == NULL ) {
1660
- if ((iter->query ->xapian ->query == NULL ) ||
1700
+ /* Master query. */
1701
+ if (iter->curr_query == -1 ) {
1702
+ if (iter->query ->xapian ->query == NULL )
1703
+ ++iter->curr_query ;
1704
+ else
1705
+ q = iter->query ->xapian ->query ;
1706
+ }
1707
+
1708
+ /* Maybe queries. */
1709
+ if ((iter->curr_query >= 0 ) &&
1710
+ (array_is_created (&iter->query ->xapian ->maybe_queries )) &&
1711
+ (array_count (&iter->query ->xapian ->maybe_queries ) > iter->curr_query )) {
1712
+ mquery = array_idx (&iter->query ->xapian ->maybe_queries ,
1713
+ iter->curr_query );
1714
+ q = mquery->query ;
1715
+ }
1716
+
1717
+ if ((q == NULL ) ||
1661
1718
((iter->db = fts_flatcurve_xapian_read_db (iter->query ->backend , opts)) == NULL ))
1662
1719
return NULL ;
1663
1720
1664
1721
iter->enquire = new Xapian::Enquire (*iter->db );
1665
1722
iter->enquire ->set_docid_order (
1666
1723
Xapian::Enquire::DONT_CARE);
1667
- iter->enquire ->set_query (*iter-> query -> xapian -> query );
1724
+ iter->enquire ->set_query (*q );
1668
1725
1669
1726
try {
1670
1727
m = iter->enquire ->get_mset (0 ,
@@ -1685,9 +1742,13 @@ fts_flatcurve_xapian_query_iter_next(struct fts_flatcurve_xapian_query_iter *ite
1685
1742
iter->i = m.begin ();
1686
1743
}
1687
1744
1688
- if (iter->i == m.end ())
1689
- return NULL ;
1745
+ if (iter->i == m.end ()) {
1746
+ fts_flatcurve_xapian_query_iter_clear_current (iter);
1747
+ ++iter->curr_query ;
1748
+ return fts_flatcurve_xapian_query_iter_next (iter);
1749
+ }
1690
1750
1751
+ iter->result ->maybe = (iter->curr_query >= 0 );
1691
1752
iter->result ->score = iter->i .get_weight ();
1692
1753
/* MSet docid can be an "interleaved" docid generated by
1693
1754
* Xapian::Database when handling multiple DBs at once. Instead, we
@@ -1707,8 +1768,7 @@ fts_flatcurve_xapian_query_iter_deinit(struct fts_flatcurve_xapian_query_iter **
1707
1768
/* Need to explicitly call dtor, or else MSet doesn't release memory
1708
1769
* allocated internally. */
1709
1770
*_iter = NULL ;
1710
- iter->i .~MSetIterator ();
1711
- delete (iter->enquire );
1771
+ fts_flatcurve_xapian_query_iter_clear_current (iter);
1712
1772
p_free (iter->query ->pool , iter->result );
1713
1773
p_free (iter->query ->pool , iter);
1714
1774
}
@@ -1723,7 +1783,10 @@ bool fts_flatcurve_xapian_run_query(struct flatcurve_fts_query *query,
1723
1783
if ((iter = fts_flatcurve_xapian_query_iter_init (query)) == NULL )
1724
1784
return FALSE ;
1725
1785
while ((result = fts_flatcurve_xapian_query_iter_next (iter)) != NULL ) {
1726
- seq_range_array_add (&r->uids , result->uid );
1786
+ if (result->maybe || query->xapian ->maybe )
1787
+ seq_range_array_add (&r->maybe_uids , result->uid );
1788
+ else
1789
+ seq_range_array_add (&r->uids , result->uid );
1727
1790
score = array_append_space (&r->scores );
1728
1791
score->score = (float )result->score ;
1729
1792
score->uid = result->uid ;
@@ -1734,7 +1797,15 @@ bool fts_flatcurve_xapian_run_query(struct flatcurve_fts_query *query,
1734
1797
1735
1798
void fts_flatcurve_xapian_destroy_query (struct flatcurve_fts_query *query)
1736
1799
{
1800
+ struct flatcurve_fts_query_xapian_maybe *mquery;
1801
+
1737
1802
delete (query->xapian ->query );
1803
+ if (array_is_created (&query->xapian ->maybe_queries )) {
1804
+ array_foreach_modifiable (&query->xapian ->maybe_queries , mquery) {
1805
+ delete (mquery->query );
1806
+ }
1807
+ array_free (&query->xapian ->maybe_queries );
1808
+ }
1738
1809
}
1739
1810
1740
1811
const char *fts_flatcurve_xapian_library_version ()
0 commit comments