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