about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--xapian.i.in19
-rw-r--r--xapian/xapian.scm27
2 files changed, 28 insertions, 18 deletions
diff --git a/xapian.i.in b/xapian.i.in
index 84695e9..ba923d4 100644
--- a/xapian.i.in
+++ b/xapian.i.in
@@ -1,5 +1,5 @@
 /* guile-xapian --- Guile bindings for Xapian
- * Copyright © 2020, 2023–2024 Arun Isaac <arunisaac@systemreboot.net>
+ * Copyright © 2020, 2023–2024, 2026 Arun Isaac <arunisaac@systemreboot.net>
  * Copyright © 2021, 2022 Bob131 <bob@bob131.so>
  *
  * This file is part of guile-xapian.
@@ -206,3 +206,20 @@ class GuileXapianFieldProcessorWrapper
   ~GuileXapianFieldProcessorWrapper();
   Xapian::Query operator()(std::string const&);
 };
+
+// Build query from subqueries. This needs to be in C++ because we
+// need to provide Xapian::Query with an iterator.
+%{
+  Xapian::Query guile_xapian_build_query(Xapian::Query::op op, SCM subqueries) {
+    int length = scm_to_int(scm_length(subqueries));
+    Xapian::Query **subqueries_arr = (Xapian::Query**) malloc(length * sizeof(Xapian::Query*));
+    for (int i=0; i<length; i++)
+      SWIG_ConvertPtr(scm_list_ref(subqueries, scm_from_int(i)),
+                      (void**)&subqueries_arr[i],
+                      SWIGTYPE_p_Xapian__Query,
+                      0);
+    return Xapian::Query(op, subqueries_arr, subqueries_arr + length);
+  }
+%}
+
+Xapian::Query guile_xapian_build_query(Xapian::Query::op, SCM);
diff --git a/xapian/xapian.scm b/xapian/xapian.scm
index d71bbe1..00a4896 100644
--- a/xapian/xapian.scm
+++ b/xapian/xapian.scm
@@ -299,17 +299,12 @@ on the database object."
   "Return a @code{Query} object for @var{term}."
   (new-Query term))
 
-(define (query-combine combine-operator default . queries)
-  (reduce-right (cut new-Query combine-operator <> <>)
-                default
-                queries))
-
 (define (query-and . queries)
   "Return a query matching only documents matching all @var{queries}.
 
 In a weighted context, the weight is the sum of the weights for all
 queries."
-  (apply query-combine (Query-OP-AND) (Query-MatchAll) queries))
+  (guile-xapian-build-query (Query-OP-AND) queries))
 
 (define (query-or . queries)
   "Return a query matching documents which at least one of @var{queries}
@@ -317,7 +312,7 @@ match.
 
 In a weighted context, the weight is the sum of the weights for
 matching queries."
-  (apply query-combine (Query-OP-OR) (Query-MatchNothing) queries))
+  (guile-xapian-build-query (Query-OP-OR) queries))
 
 (define (query-xor . queries)
   "Return a query matching documents which an odd number of @var{queries}
@@ -325,7 +320,7 @@ match.
 
 In a weighted context, the weight is the sum of the weights for
 matching queries."
-  (apply query-combine (Query-OP-XOR) (Query-MatchNothing) queries))
+  (guile-xapian-build-query (Query-OP-XOR) queries))
 
 (define (query-filter . queries)
   "Return a query matching only documents matching all @var{queries},
@@ -333,19 +328,17 @@ but only take weight from the first of @var{queries}.
 
 In a non-weighted context, @code{query-filter} and @code{query-and}
 are equivalent."
-  (apply query-combine (Query-OP-FILTER) (Query-MatchAll) queries))
+  (guile-xapian-build-query (Query-OP-FILTER) queries))
 
-(define (query-phrase first-query . other-queries)
-  "Return a query matching only documents where @var{first-query} and all
-of @var{other-queries} match near and in order. All queries must be
-single-term queries (constructed using @code{query}) or single-term
-queries composed with @code{query-or}.
+(define (query-phrase . queries)
+  "Return a query matching only documents where all @var{queries} match
+near and in order. All queries must be single-term
+queries (constructed using @code{query}) or single-term queries
+composed with @code{query-or}.
 
 In a weighted context, the weight is the sum of the weights for all
 queries."
-  (new-Query (Query-OP-PHRASE)
-             first-query
-             (apply query-or other-queries)))
+  (guile-xapian-build-query (Query-OP-PHRASE) queries))
 
 
 (define* (prefixed-range-processor slot proc #:key (prefix "") repeated?)