]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/fts.pm
Post-2.5-m1 whitespace fixup
[Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / Application / Storage / Driver / Pg / fts.pm
1 { # Every driver needs to provide a 'compile()' method to OpenILS::Application::Storage::FTS.
2   # If that driver wants to support FTI, that is...
3     #-------------------------------------------------------------------------------
4     package OpenILS::Application::Storage::FTS;
5     use OpenSRF::Utils::Logger qw/:level/;
6     use Unicode::Normalize;
7     my $log = 'OpenSRF::Utils::Logger';
8
9     sub compile {
10         my $self = shift;
11         my $class = shift;
12         my $term = NFD(shift());
13
14         $log->debug("Raw term: $term",DEBUG);
15         $log->debug("Search class: $class",DEBUG);
16
17         $term =~ s/\&//go;
18         $term =~ s/\|//go;
19
20         $self = ref($self) || $self;
21         $self = bless {} => $self;
22         $self->{class} = $class;
23
24         $term =~ s/(\pM+)//gos;
25         $term =~ s/(\b\.\b)//gos;
26
27         # hack to normalize ratio-like strings
28         while ($term =~ /\b\d{1}:[, ]?\d+(?:[ ,]\d+[^:])+/o) {
29             $term = $` . join ('', split(/[, ]/, $&)) . $';
30         }
31
32         $self->decompose($term);
33
34         my $newterm = '';
35         $newterm = join('&', $self->words) if ($self->words);
36
37         if (@{$self->nots}) {
38             $newterm = '('.$newterm.')&' if ($newterm);
39             $newterm .= '!('. join('|', $self->nots) . ')';
40         }
41
42         $log->debug("Compiled term is [$newterm]", DEBUG);
43         $newterm = OpenILS::Application::Storage::Driver::Pg->quote($newterm);
44         $log->debug("Quoted term is [$newterm]", DEBUG);
45
46         $self->{fts_query} = ["to_tsquery('$$self{class}',$newterm)"];
47         $self->{fts_query_nots} = [];
48         $self->{fts_op} = '@@';
49         $self->{text_col} = shift;
50         $self->{fts_col} = shift;
51
52         return $self;
53     }
54
55     sub sql_where_clause {
56         my $self = shift;
57         my $column = $self->fts_col;
58         my @output;
59     
60         my @ranks;
61         for my $fts ( $self->fts_query ) {
62             push @output, join(' ', $self->fts_col, $self->{fts_op}, $fts);
63             push @ranks, "ts_rank($column, $fts)";
64         }
65         $self->{fts_rank} = \@ranks;
66     
67         my $phrase_match = $self->sql_exact_phrase_match();
68         return join(' AND ', @output) . $phrase_match;
69     }
70
71     sub sql_exact_phrase_match {
72         my $self = shift;
73         my $column = $self->text_col;
74         my $output = '';
75         for my $phrase ( $self->phrases ) {
76             $phrase =~ s/\*/\\*/go;
77             $phrase =~ s/\./\\./go;
78             $phrase =~ s/'/\\'/go;
79             $phrase =~ s/\s+/\\s+/go;
80             $log->debug("Adding phrase [$phrase] to the match list", DEBUG);
81             $output .= " AND $column ~* \$\$(^|\\W+)$phrase(\\W+|\$)\$\$";
82         }
83         $log->debug("Phrase list is [$output]", DEBUG);
84         return $output;
85     }
86
87 }
88
89 1;