# This is as close as we can get to doing full text search using
# standard ANSI SQL, without real full text search support. DB specific
- # modules shoud override this, as this will be always much slower.
-
- # the text is already sql-quoted, so we need to remove the quotes first
- my $quote = substr($self->quote(''), 0, 1);
- $text = $1 if ($text =~ /^$quote(.*)$quote$/);
+ # modules should override this, as this will be always much slower.
# make the string lowercase to do case insensitive search
my $lower_text = lc($text);
- # split the text we search for to separate words
+ # split the text we search for into separate words
my @words = split(/\s+/, $lower_text);
- # search for occurence of all specified words in the column
- return "CASE WHEN (LOWER($column) LIKE ${quote}%" .
- join("%${quote} AND LOWER($column) LIKE ${quote}%", @words) .
- "%${quote}) THEN 1 ELSE 0 END";
+ # surround the words with wildcards and SQL quotes so we can use them
+ # in LIKE search clauses
+ @words = map($self->quote("%$_%"), @words);
+
+ # turn the words into a set of LIKE search clauses
+ @words = map("LOWER($column) LIKE $_", @words);
+
+ # search for occurrences of all specified words in the column
+ return "CASE WHEN (" . join(" AND ", @words) . ") THEN 1 ELSE 0 END";
}
#####################################################################
specified text on a given column.
There is a ANSI SQL version of this method implemented using
LIKE operator, but it's not a real full text search. DB specific
- modules shoud override this, as this generic implementation will
+ modules should override this, as this generic implementation will
be always much slower. This generic implementation returns
'relevance' as 0 for no match, or 1 for a match.
Params: $column = name of column to search (scalar)
$text = text to search for (scalar)
- Returns: formatted SQL for for full text search
+ Returns: formatted SQL for full text search
=item C<sql_istrcmp>
use strict;
+use Bugzilla::Util;
use Bugzilla::Error;
# This module extends the DB interface via inheritance
sub sql_fulltext_search {
my ($self, $column, $text) = @_;
- return "MATCH($column) AGAINST($text)";
+ # Add the boolean mode modifier if the search string contains
+ # boolean operators.
+ my $mode = ($text =~ /[+-<>()~*"]/ ? "IN BOOLEAN MODE" : "");
+
+ # quote the text for use in the MATCH AGAINST expression
+ $text = $self->quote($text);
+
+ # untaint the text, since it's safe to use now that we've quoted it
+ trick_taint($text);
+
+ return "MATCH($column) AGAINST($text $mode)";
}
sub sql_istring {
# $term1 searches comments.
# $term2 searches summaries, which contributes to the relevance
# ranking in SELECT but doesn't limit which bugs get retrieved.
- my $term1 = $dbh->sql_fulltext_search("${table}.thetext",
- ::SqlQuote($v));
- my $term2 = $dbh->sql_fulltext_search("bugs.short_desc",
- ::SqlQuote($v));
+ my $term1 = $dbh->sql_fulltext_search("${table}.thetext", $v);
+ my $term2 = $dbh->sql_fulltext_search("bugs.short_desc", $v);
# The term to use in the WHERE clause.
$term = "$term1 > 0";