1 %{
2 /* perl/extra.i: custom Perl code for xapian-bindings
3  *
4  * Based on the perl XS wrapper files.
5  *
6  * Copyright (C) 2009 Kosei Moriyama
7  * Copyright (C) 2011,2012,2013,2015,2016,2018,2019,2020 Olly Betts
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
22  * USA
23  */
24 %}
25 
26 /* Perl code */
27 %perlcode {
28 package Xapian;
29 
30 our $VERSION = PERL_XAPIAN_VERSION;
31 };
32 %perlcode %{
33 # We need to use the RTLD_GLOBAL flag to dlopen() so that other C++
34 # modules that link against libxapian.so get the *same* value for all the
35 # weak symbols (eg, the exception classes)
36 sub dl_load_flags { 0x01 }
37 
38 # Items to export into caller's namespace by default. Note: do not export
39 # names by default without a very good reason. Use EXPORT_OK instead.
40 # Do not simply export all your public functions/methods/constants.
41 
42 # This allows declaration use Xapian ':all';
43 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
44 # will save memory.
45 our %EXPORT_TAGS = (
46 		    'ops' => [ qw(
47 				  OP_AND
48 				  OP_OR
49 				  OP_AND_NOT
50 				  OP_XOR
51 				  OP_AND_MAYBE
52 				  OP_FILTER
53 				  OP_NEAR
54 				  OP_PHRASE
55 				  OP_VALUE_RANGE
56 				  OP_SCALE_WEIGHT
57 				  OP_ELITE_SET
58 				  OP_VALUE_GE
59 				  OP_VALUE_LE
60 				 ) ],
61 		    'db' => [ qw(
62 				 DB_OPEN
63 				 DB_CREATE
64 				 DB_CREATE_OR_OPEN
65 				 DB_CREATE_OR_OVERWRITE
66 				 ) ],
67 		    'enq_order' => [ qw(
68 				 ENQ_DESCENDING
69 				 ENQ_ASCENDING
70 				 ENQ_DONT_CARE
71 				   ) ],
72 		    'qpflags' => [ qw(
73 				 FLAG_BOOLEAN
74 				 FLAG_PHRASE
75 				 FLAG_LOVEHATE
76 				 FLAG_BOOLEAN_ANY_CASE
77 				 FLAG_WILDCARD
78 				 FLAG_PURE_NOT
79 				 FLAG_PARTIAL
80 				 FLAG_SPELLING_CORRECTION
81 				 FLAG_SYNONYM
82 				 FLAG_AUTO_SYNONYMS
83 				 FLAG_AUTO_MULTIWORD_SYNONYMS
84 				 FLAG_CJK_NGRAM
85 				 FLAG_DEFAULT
86 				 ) ],
87 		    'qpstem' => [ qw(
88 				 STEM_NONE
89 				 STEM_SOME
90 				 STEM_SOME_FULL_POS
91 				 STEM_ALL
92 				 STEM_ALL_Z
93 				 ) ]
94 		   );
95 $EXPORT_TAGS{standard} = [ @{ $EXPORT_TAGS{'ops'} },
96 			   @{ $EXPORT_TAGS{'db'} },
97 			   @{ $EXPORT_TAGS{'qpflags'} },
98 			   @{ $EXPORT_TAGS{'qpstem'} } ];
99 $EXPORT_TAGS{all} = [ @{ $EXPORT_TAGS{'standard'} }, @{ $EXPORT_TAGS{'enq_order'} } ];
100 
101 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
102 
103 # Preloaded methods go here.
104 
105 our @OP_NAMES;
106 foreach (@{ $EXPORT_TAGS{'ops'} }) {
107   $OP_NAMES[eval $_] = $_;
108 }
109 
110 our @DB_NAMES;
111 foreach (@{ $EXPORT_TAGS{'db'} }) {
112   $DB_NAMES[eval $_] = $_;
113 }
114 
115 our @FLAG_NAMES;
116 foreach (@{ $EXPORT_TAGS{'qpflags'} }) {
117   $FLAG_NAMES[eval $_] = $_;
118 }
119 
120 our @STEM_NAMES;
121 foreach (@{ $EXPORT_TAGS{'qpstem'} }) {
122   $STEM_NAMES[eval $_] = $_;
123 }
124 
125 # Compatibility wrapping for Xapian::BAD_VALUENO (wrapped as a constant since
126 # xapian-bindings 1.4.10).
127 our $BAD_VALUENO = BAD_VALUENO;
128 
129 sub search_xapian_compat {
130     *Search::Xapian:: = \%Xapian::;
131     *Search::Xapian::VERSION = \$VERSION;
132     *Search::Xapian::OP_NAMES = \@OP_NAMES;
133     *Search::Xapian::DB_NAMES = \@DB_NAMES;
134     *Search::Xapian::FLAG_NAMES = \@FLAG_NAMES;
135     *Search::Xapian::STEM_NAMES = \@STEM_NAMES;
136     *Search::Xapian::BAD_VALUENO = \&BAD_VALUENO;
137     *Search::Xapian::DB_OPEN = \&DB_OPEN;
138     *Search::Xapian::DB_CREATE = \&DB_CREATE;
139     *Search::Xapian::DB_CREATE_OR_OPEN = \&DB_CREATE_OR_OPEN;
140     *Search::Xapian::DB_CREATE_OR_OVERWRITE = \&DB_CREATE_OR_OVERWRITE;
141     *Search::Xapian::version_string = \&version_string;
142     *Search::Xapian::major_version = \&major_version;
143     *Search::Xapian::minor_version = \&minor_version;
144     *Search::Xapian::revision = \&revision;
145     *Search::Xapian::sortable_serialise = \&sortable_serialise;
146     *Search::Xapian::sortable_unserialise = \&sortable_unserialise;
147 }
148 
149 package Xapian::Database;
150 sub enquire {
151   my $self = shift;
152   my $enquire = Xapian::Enquire->new( $self );
153   if( @_ ) {
154     $enquire->set_query( @_ );
155   }
156   return $enquire;
157 }
158 
159 package Xapian::Enquire;
160 sub matches {
161   my $self = shift;
162   return $self->get_mset(@_)->items();
163 }
164 
165 package Xapian::ESet;
166 sub items {
167   my $self = shift;
168   my @array;
169   tie( @array, 'Xapian::ESet', $self );
170   return @array;
171 }
172 
173 use overload '++' => sub { $_[0]->inc() },
174 	     '--' => sub { $_[0]->dec() },
175 	     '='  => sub { $_[0]->clone() },
176 	     'eq' => sub { $_[0]->equal($_[1]) },
177 	     'ne' => sub { $_[0]->nequal($_[1]) },
178 	     '==' => sub { $_[0]->equal($_[1]) },
179 	     '!=' => sub { $_[0]->nequal($_[1]) },
180 	     'fallback' => 1;
181 
182 sub clone() {
183   my $self = shift;
184   my $class = ref( $self );
185   my $copy = new( $self );
186   bless $copy, $class;
187   return $copy;
188 }
189 
190 sub TIEARRAY {
191   my $class = shift;
192   my $eset = shift;
193   return bless $eset, $class;
194 }
195 
196 sub FETCHSIZE {
197     my $self = shift;
198     return $self->size();
199 }
200 
201 package Xapian::ESetIterator;
202 use overload '++' => sub { $_[0]->inc() },
203 	     '--' => sub { $_[0]->dec() },
204 	     '='  => sub { $_[0]->clone() },
205 	     'eq' => sub { $_[0]->equal($_[1]) },
206 	     'ne' => sub { $_[0]->nequal($_[1]) },
207 	     '==' => sub { $_[0]->equal($_[1]) },
208 	     '!=' => sub { $_[0]->nequal($_[1]) },
209 	     'fallback' => 1;
210 
211 sub clone() {
212   my $self = shift;
213   my $class = ref( $self );
214   my $copy = new( $self );
215   bless $copy, $class;
216   return $copy;
217 }
218 
219 package Xapian::MSet;
220 sub items {
221   my $self = shift;
222   my @array;
223   tie( @array, 'Xapian::MSet::Tied', $self );
224   return @array;
225 }
226 
227 sub TIEARRAY {
228   my $class = shift;
229   my $mset = shift;
230   return bless $mset, $class;
231 }
232 
233 sub FETCHSIZE {
234     my $self = shift;
235     return $self->size();
236 }
237 
238 package Xapian::MSetIterator;
239 use overload '++' => sub { $_[0]->inc() },
240 	     '--' => sub { $_[0]->dec() },
241 	     '='  => sub { $_[0]->clone() },
242 	     'eq' => sub { $_[0]->equal($_[1]) },
243 	     'ne' => sub { $_[0]->nequal($_[1]) },
244 	     '==' => sub { $_[0]->equal($_[1]) },
245 	     '!=' => sub { $_[0]->nequal($_[1]) },
246 	     'fallback' => 1;
247 
248 sub clone() {
249   my $self = shift;
250   my $class = ref( $self );
251   bless $self, $class;
252   return $self;
253 }
254 
255 package Xapian::MSet::Tied;
256 our @ISA = qw(Xapian::MSet);
257 
258 package Xapian::PositionIterator;
259 use overload '++' => sub { $_[0]->inc() },
260 	     '='  => sub { $_[0]->clone() },
261 	     'eq' => sub { $_[0]->equal($_[1]) },
262 	     'ne' => sub { $_[0]->nequal($_[1]) },
263 	     '==' => sub { $_[0]->equal($_[1]) },
264 	     '!=' => sub { $_[0]->nequal($_[1]) },
265 	     'fallback' => 1;
266 
267 sub clone() {
268   my $self = shift;
269   my $class = ref( $self );
270   my $copy = new( $self );
271   bless $copy, $class;
272   return $copy;
273 }
274 
275 package Xapian::PostingIterator;
276 use overload '++' => sub { $_[0]->inc() },
277 	     '='  => sub { $_[0]->clone() },
278 	     'eq' => sub { $_[0]->equal($_[1]) },
279 	     'ne' => sub { $_[0]->nequal($_[1]) },
280 	     '==' => sub { $_[0]->equal($_[1]) },
281 	     '!=' => sub { $_[0]->nequal($_[1]) },
282 	     'fallback' => 1;
283 
284 sub clone() {
285   my $self = shift;
286   my $class = ref( $self );
287   my $copy = new( $self );
288   bless $copy, $class;
289   return $copy;
290 }
291 
292 package Xapian::TermGenerator;
293 sub set_stopper {
294     my ($self, $stopper) = @_;
295     $self{_stopper} = $stopper;
296     set_stopper1( @_ );
297 }
298 
299 package Xapian::TermIterator;
300 use overload '++' => sub { $_[0]->inc() },
301 	     '='  => sub { $_[0]->clone() },
302 	     'eq' => sub { $_[0]->equal($_[1]) },
303 	     'ne' => sub { $_[0]->nequal($_[1]) },
304 	     '==' => sub { $_[0]->equal($_[1]) },
305 	     '!=' => sub { $_[0]->nequal($_[1]) },
306 	     'fallback' => 1;
307 
308 sub clone() {
309   my $self = shift;
310   my $class = ref( $self );
311   my $copy = new( $self );
312   bless $copy, $class;
313   return $copy;
314 }
315 
316 package Xapian::ValueIterator;
317 use overload '++' => sub { $_[0]->inc() },
318 	     '='  => sub { $_[0]->clone() },
319 	     'eq' => sub { $_[0]->equal($_[1]) },
320 	     'ne' => sub { $_[0]->nequal($_[1]) },
321 	     '==' => sub { $_[0]->equal($_[1]) },
322 	     '!=' => sub { $_[0]->nequal($_[1]) },
323 	     'fallback' => 1;
324 
325 sub clone() {
326   my $self = shift;
327   my $class = ref( $self );
328   my $copy = new( $self );
329   bless $copy, $class;
330   return $copy;
331 }
332 
333 # Adding CLONE_SKIP functions
334 package Xapian::LogicError;
335 sub CLONE_SKIP { 1 }
336 package Xapian::PositionIterator;
337 sub CLONE_SKIP { 1 }
338 package Xapian::PostingIterator;
339 sub CLONE_SKIP { 1 }
340 package Xapian::TermIterator;
341 sub CLONE_SKIP { 1 }
342 package Xapian::ValueIterator;
343 sub CLONE_SKIP { 1 }
344 package Xapian::Document;
345 sub CLONE_SKIP { 1 }
346 package Xapian::PostingSource;
347 sub CLONE_SKIP { 1 }
348 package Xapian::ValuePostingSource;
349 sub CLONE_SKIP { 1 }
350 package Xapian::ValueWeightPostingSource;
351 sub CLONE_SKIP { 1 }
352 package Xapian::ValueMapPostingSource;
353 sub CLONE_SKIP { 1 }
354 package Xapian::FixedWeightPostingSource;
355 sub CLONE_SKIP { 1 }
356 package Xapian::MSet;
357 sub CLONE_SKIP { 1 }
358 package Xapian::MSetIterator;
359 sub CLONE_SKIP { 1 }
360 package Xapian::ESet;
361 sub CLONE_SKIP { 1 }
362 package Xapian::ESetIterator;
363 sub CLONE_SKIP { 1 }
364 package Xapian::RSet;
365 sub CLONE_SKIP { 1 }
366 package Xapian::MatchDecider;
367 sub CLONE_SKIP { 1 }
368 package Xapian::Enquire;
369 sub CLONE_SKIP { 1 }
370 package Xapian::Weight;
371 sub CLONE_SKIP { 1 }
372 package Xapian::BoolWeight;
373 sub CLONE_SKIP { 1 }
374 package Xapian::BM25Weight;
375 sub CLONE_SKIP { 1 }
376 package Xapian::TradWeight;
377 sub CLONE_SKIP { 1 }
378 package Xapian::Database;
379 sub CLONE_SKIP { 1 }
380 package Xapian::WritableDatabase;
381 sub CLONE_SKIP { 1 }
382 package Xapian::Query;
383 sub MatchAll { Xapianc::new_Query('') }
384 sub MatchNothing { Xapianc::new_Query() }
385 sub CLONE_SKIP { 1 }
386 package Xapian::Stopper;
387 sub CLONE_SKIP { 1 }
388 package Xapian::SimpleStopper;
389 sub CLONE_SKIP { 1 }
390 package Xapian::RangeProcessor;
391 sub CLONE_SKIP { 1 }
392 package Xapian::DateRangeProcessor;
393 sub CLONE_SKIP { 1 }
394 package Xapian::NumberRangeProcessor;
395 sub CLONE_SKIP { 1 }
396 package Xapian::ValueRangeProcessor;
397 sub CLONE_SKIP { 1 }
398 package Xapian::StringValueRangeProcessor;
399 sub CLONE_SKIP { 1 }
400 package Xapian::DateValueRangeProcessor;
401 sub CLONE_SKIP { 1 }
402 package Xapian::NumberValueRangeProcessor;
403 sub CLONE_SKIP { 1 }
404 package Xapian::FieldProcessor;
405 sub CLONE_SKIP { 1 }
406 package Xapian::QueryParser;
407 sub CLONE_SKIP { 1 }
408 package Xapian::Stem;
409 sub CLONE_SKIP { 1 }
410 package Xapian::TermGenerator;
411 sub CLONE_SKIP { 1 }
412 package Xapian::Sorter;
413 sub CLONE_SKIP { 1 }
414 package Xapian::MultiValueSorter;
415 sub CLONE_SKIP { 1 }
416 package Xapian::ReplicationInfo;
417 sub CLONE_SKIP { 1 }
418 package Xapian::DatabaseMaster;
419 sub CLONE_SKIP { 1 }
420 package Xapian::DatabaseReplica;
421 sub CLONE_SKIP { 1 }
422 package Xapian::ValueSetMatchDecider;
423 sub CLONE_SKIP { 1 }
424 package Xapian::SerialisationContext;
425 sub CLONE_SKIP { 1 }
426 package Xapian::MSet::Tied;
427 sub CLONE_SKIP { 1 }
428 
429 # Pod document of Xapian
430 =encoding utf8
431 =head1 NAME
432 
433 Xapian - Perl frontend to the Xapian C++ search library.
434 
435 =head1 SYNOPSIS
436 
437   use Xapian;
438 
439   my $parser = Xapian::QueryParser->new();
440   my $query = $parser->parse_query( '[QUERY STRING]' );
441 
442   my $db = Xapian::Database->new( '[DATABASE DIR]' );
443   my $enq = $db->enquire();
444 
445   printf "Running query '%s'\n", $query->get_description();
446 
447   $enq->set_query( $query );
448   my @matches = $enq->matches(0, 10);
449 
450   print scalar(@matches) . " results found\n";
451 
452   foreach my $match ( @matches ) {
453     my $doc = $match->get_document();
454     printf "ID %d %d%% [ %s ]\n", $match->get_docid(), $match->get_percent(), $doc->get_data();
455   }
456 
457 =head1 DESCRIPTION
458 
459 This module is a pretty-much complete wrapping of the Xapian C++ API.  The
460 main omissions are features which aren't useful to wrap for Perl, such as
461 Xapian::UTF8Iterator.
462 
463 This module is generated using SWIG.  It is intended as a replacement for
464 the older Search::Xapian module which is easier to keep up to date and
465 which more completely wraps the C++ API.  It is largely compatible with
466 Search::Xapian, but see the COMPATIBILITY section below if you have code using
467 Search::Xapian which you want to get working with this new module.
468 
469 There are some gaps in the POD documentation for wrapped classes, but you
470 can read the Xapian C++ API documentation at
471 L<https://xapian.org/docs/apidoc/html/annotated.html> for details of
472 these.  Alternatively, take a look at the code in the examples and tests.
473 
474 If you want to use Xapian and the threads module together, make
475 sure you're using Perl >= 5.8.7 as then Xapian uses CLONE_SKIP to make sure
476 that the perl wrapper objects aren't copied to new threads - without this the
477 underlying C++ objects can get destroyed more than once which leads to
478 undefined behaviour.
479 
480 If you encounter problems, or have any comments, suggestions, patches, etc
481 please email the Xapian-discuss mailing list (details of which can be found at
482 L<https://xapian.org/lists>).
483 
484 =head2 COMPATIBILITY
485 
486 This module is mostly compatible with Search::Xapian.  The following are known
487 differences, with details of how to write code which works with both.
488 
489 Search::Xapian overloads stringification - e.g. C<"$query"> is equivalent to
490 C<$query->get_description()>, while C<"$termiterator"> is equivalent to
491 C<$termiterator->get_term()>.  This module doesn't support overloaded
492 stringification, so you should instead explicitly call the method you
493 want.  The technical reason for this change is that stringification is hard to
494 support in SWIG-generated bindings, but this context-sensitive stringification
495 where the operation performed depends on the object type seems unhelpful in
496 hindsight anyway.
497 
498 Search::Xapian overloads conversion to an integer for some classes - e.g.
499 C<0+$positioniterator> is equivalent to C<$positioniterator->get_termpos>
500 while C<0+$postingiterator> is equivalent to C<$postingiterator->get_docid>.
501 This module doesn't provide these overloads so you should instead explicitly
502 call the method you want.  As above, we think this context-sensitive behaviour
503 wasn't helpful in hindsight.
504 
505 This module is fussier about whether a passed scalar value is a string or
506 an integer than Search::Xapian, so e.g. C<Xapian::Query->new(2001)> will fail
507 but the equivalent worked with Search::Xapian.  If C<$term> might not be a
508 string use C<Xapian::Query->new("$term")> to ensure it is converted to a
509 string.  The new behaviour isn't very Perlish, but is likely to be hard to
510 address universally as it comes from SWIG.  Let us know if you find particular
511 places where it's annoying and we can look at addressing those.
512 
513 Both this module and Search::Xapian support passing a Perl sub (which can be
514 anonymous) for the functor classes C<MatchDecider> and C<ExpandDecider>.  In
515 some cases Search::Xapian accepts a string naming a Perl sub, but this module
516 never accepts this.  Instead of passing C<"::mymatchdecider">, pass
517 C<\&mymatchdecider> which will work with either module.  If you really want to
518 dynamically specify the function name, you can pass C<sub {eval
519 "&$dynamicmatchdecider"}>.
520 
521 Search::Xapian provides a PerlStopper class which is supposed to be
522 subclassable in Perl to implement your own stopper, but this mechanism doesn't
523 actually seem to work.  This module instead supports user-implemented stoppers
524 by accepting a Perl sub in place of a Stopper object.
525 
526 =head3 Importing Either Module
527 
528 If you want your code to use either this module or Search::Xapian depending
529 what's installed, then instead of C<use Search::Xapian (':all');> you can use:
530 
531   BEGIN {
532     eval {
533       require Xapian;
534       Xapian->import(':all');
535       Xapian::search_xapian_compat();
536     };
537     if ($@) {
538       require Search::Xapian;
539       Search::Xapian->import(':all');
540     }
541   }
542 
543 If you just C<use Search::Xapian;> then the C<import()> calls aren't needed.
544 
545 The C<Xapian::search_xapian_compat()> call sets up aliases in the
546 C<Search::Xapian> namespace so you can write code which refers to
547 C<Search::Xapian> but can actually use this module instead.
548 
549 =head2 EXPORT
550 
551 None by default.
552 
553 =head1 :db
554 
555 =over 4
556 
557 =item DB_OPEN
558 
559 Open a database, fail if database doesn't exist.
560 
561 =item DB_CREATE
562 
563 Create a new database, fail if database exists.
564 
565 =item DB_CREATE_OR_OPEN
566 
567 Open an existing database, without destroying data, or create a new
568 database if one doesn't already exist.
569 
570 =item DB_CREATE_OR_OVERWRITE
571 
572 Overwrite database if it exists.
573 
574 =back
575 
576 =head1 :ops
577 
578 =over 4
579 
580 =item OP_AND
581 
582 Match if both subqueries are satisfied.
583 
584 =item OP_OR
585 
586 Match if either subquery is satisfied.
587 
588 =item OP_AND_NOT
589 
590 Match if left but not right subquery is satisfied.
591 
592 =item OP_XOR
593 
594 Match if left or right, but not both queries are satisfied.
595 
596 =item OP_AND_MAYBE
597 
598 Match if left is satisfied, but use weights from both.
599 
600 =item OP_FILTER
601 
602 Like OP_AND, but only weight using the left query.
603 
604 =item OP_NEAR
605 
606 Match if the words are near each other. The window should be specified, as
607 a parameter to C<Xapian::Query->new()>, but it defaults to the
608 number of terms in the list.
609 
610 =item OP_PHRASE
611 
612 Match as a phrase (All words in order).
613 
614 =item OP_ELITE_SET
615 
616 Select an elite set from the subqueries, and perform a query with these combined as an OR query.
617 
618 =item OP_VALUE_RANGE
619 
620 Filter by a range test on a document value.
621 
622 =back
623 
624 =head1 :qpflags
625 
626 =over 4
627 
628 =item FLAG_DEFAULT
629 
630 This gives the QueryParser default flag settings, allowing you to easily add
631 flags to the default ones.
632 
633 =item FLAG_BOOLEAN
634 
635 Support AND, OR, etc and bracketted subexpressions.
636 
637 =item FLAG_LOVEHATE
638 
639 Support + and -.
640 
641 =item FLAG_PHRASE
642 
643 Support quoted phrases.
644 
645 =item FLAG_BOOLEAN_ANY_CASE
646 
647 Support AND, OR, etc even if they aren't in ALLCAPS.
648 
649 =item FLAG_WILDCARD
650 
651 Support right truncation (e.g. Xap*).
652 
653 =item FLAG_PURE_NOT
654 
655 Allow queries such as 'NOT apples'.
656 
657 These require the use of a list of all documents in the database
658 which is potentially expensive, so this feature isn't enabled by
659 default.
660 
661 =item FLAG_PARTIAL
662 
663 Enable partial matching.
664 
665 Partial matching causes the parser to treat the query as a
666 "partially entered" search.  This will automatically treat the
667 final word as a wildcarded match, unless it is followed by
668 whitespace, to produce more stable results from interactive
669 searches.
670 
671 =item FLAG_SPELLING_CORRECTION
672 
673 =item FLAG_SYNONYM
674 
675 =item FLAG_AUTO_SYNONYMS
676 
677 =item FLAG_AUTO_MULTIWORD_SYNONYMS
678 
679 =back
680 
681 =head1 :qpstem
682 
683 =over 4
684 
685 =item STEM_ALL
686 
687 Stem all terms.
688 
689 =item STEM_ALL_Z
690 
691 Stem all terms and add a "Z" prefix.
692 
693 =item STEM_NONE
694 
695 Don't stem any terms.
696 
697 =item STEM_SOME
698 
699 Stem some terms, in a manner compatible with Omega (capitalised words and those
700 in phrases aren't stemmed).
701 
702 =item STEM_SOME_FULL_POS
703 
704 Like STEM_SOME but also store term positions for stemmed terms.
705 
706 =back
707 
708 =head1 :enq_order
709 
710 =over 4
711 
712 =item ENQ_ASCENDING
713 
714 docids sort in ascending order (default)
715 
716 =item ENQ_DESCENDING
717 
718 docids sort in descending order
719 
720 =item ENQ_DONT_CARE
721 
722 docids sort in whatever order is most efficient for the backend
723 
724 =back
725 
726 =head1 :standard
727 
728 Standard is db + ops + qpflags + qpstem
729 
730 =head1 Version functions
731 
732 =over 4
733 
734 =item major_version
735 
736 Returns the major version of the Xapian C++ library being used.  E.g. for
737 Xapian 1.4.15 this would return 1.
738 
739 =item minor_version
740 
741 Returns the minor version of the Xapian C++ library being used.  E.g. for
742 Xapian 1.4.15 this would return 4.
743 
744 =item revision
745 
746 Returns the revision of the Xapian C++ library being used.  E.g. for
747 Xapian 1.4.15 this would return 15.  In a stable release series, Xapian
748 libraries with the same minor and major versions are usually ABI compatible, so
749 this often won't match the third component of C<$Xapian::VERSION> (which is the
750 version of the Xapian wrappers).
751 
752 =back
753 
754 =head1 Numeric encoding functions
755 
756 =over 4
757 
758 =item sortable_serialise NUMBER
759 
760 Convert a floating point number to a string, preserving sort order.
761 
762 This method converts a floating point number to a string, suitable for
763 using as a value for numeric range restriction, or for use as a sort
764 key.
765 
766 The conversion is platform independent.
767 
768 The conversion attempts to ensure that, for any pair of values supplied
769 to the conversion algorithm, the result of comparing the original
770 values (with a numeric comparison operator) will be the same as the
771 result of comparing the resulting values (with a string comparison
772 operator).  On platforms which represent doubles with the precisions
773 specified by IEEE_754, this will be the case: if the representation of
774 doubles is more precise, it is possible that two very close doubles
775 will be mapped to the same string, so will compare equal.
776 
777 Note also that both zero and -zero will be converted to the same
778 representation: since these compare equal, this satisfies the
779 comparison constraint, but it's worth knowing this if you wish to use
780 the encoding in some situation where this distinction matters.
781 
782 Handling of NaN isn't (currently) guaranteed to be sensible.
783 
784 =item sortable_unserialise SERIALISED_NUMBER
785 
786 Convert a string encoded using sortable_serialise back to a floating
787 point number.
788 
789 This expects the input to be a string produced by C<sortable_serialise()>.
790 If the input is not such a string, the value returned is undefined (but
791 no error will be thrown).
792 
793 The result of the conversion will be exactly the value which was
794 supplied to C<sortable_serialise()> when making the string on platforms
795 which represent doubles with the precisions specified by IEEE_754, but
796 may be a different (nearby) value on other platforms.
797 
798 =back
799 
800 =head1 TODO
801 
802 =over 4
803 
804 =item Documentation
805 
806 Add POD documentation for all classes, where possible just adapted from Xapian
807 docs.
808 
809 =item Unwrapped classes
810 
811 The following Xapian classes are not yet wrapped:
812 ErrorHandler, user-defined Weight subclasses.
813 
814 =back
815 
816 =head1 CREDITS
817 
818 These SWIG-generated Perl bindings were originally implemented by Kosei
819 Moriyama in GSoC 2009, and made their debut in the 1.2.4 release.
820 
821 They take a lot of inspiration and some code from Search::Xapian, a set
822 of hand-written XS bindings, originally written by Alex Bowley, and later
823 maintained by Olly Betts.
824 
825 Search::Xapian owed thanks to Tye McQueen E<lt>tye@metronet.comE<gt> for
826 explaining the finer points of how best to write XS frontends to C++ libraries,
827 and James Aylett E<lt>james@tartarus.orgE<gt> for clarifying the less obvious
828 aspects of the Xapian API.  Patches for wrapping missing classes and other
829 things were contributed by Olly Betts, Tim Brody, Marcus Ramberg, Peter Karman,
830 Benjamin Smith, Rusty Conover, Frank Lichtenheld, Henry Combrinck, Jess
831 Robinson, David F. Skoll, Dave O'Neill, Andreas Marienborg, Adam Sjøgren,
832 Dmitry Karasik, and Val Rosca.
833 
834 =head1 AUTHOR
835 
836 Please report any bugs/suggestions to E<lt>xapian-discuss@lists.xapian.orgE<gt>
837 or use the Xapian bug tracker L<https://xapian.org/bugs>.  Please do
838 NOT use the CPAN bug tracker or mail contributors individually.
839 
840 =head1 LICENSE
841 
842 This program is free software; you can redistribute it and/or modify
843 it under the same terms as Perl itself.
844 
845 =head1 SEE ALSO
846 
847 L<Xapian::BM25Weight>,
848 L<Xapian::BoolWeight>,
849 L<Xapian::Database>,
850 L<Xapian::Document>,
851 L<Xapian::Enquire>,
852 L<Xapian::MultiValueSorter>,
853 L<Xapian::PositionIterator>,
854 L<Xapian::PostingIterator>,
855 L<Xapian::Query>,
856 L<Xapian::QueryParser>,
857 L<Xapian::Stem>,
858 L<Xapian::TermGenerator>,
859 L<Xapian::TermIterator>,
860 L<Xapian::TradWeight>,
861 L<Xapian::ValueIterator>,
862 L<Xapian::Weight>,
863 L<Xapian::WritableDatabase>,
864 and
865 L<https://xapian.org/>.
866 
867 =cut
868 %}
869