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
clone()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