]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 281582: Replace CONCAT and MATCH with Bugzilla::DB function call (Note: This...
authormkanat%kerio.com <>
Wed, 9 Mar 2005 07:23:30 +0000 (07:23 +0000)
committermkanat%kerio.com <>
Wed, 9 Mar 2005 07:23:30 +0000 (07:23 +0000)
Patch By Tomas Kopal <Tomas.Kopal@altap.cz> r=mkanat, a=myk

Bugzilla/DB.pm
Bugzilla/DB/Mysql.pm
Bugzilla/DB/Pg.pm
Bugzilla/Search.pm

index 326e6cf63f98a6014236ef3836c0983dfa47e468..1dccf535a874df2e8ddf2cdfc7ba424ffbb7da68 100644 (file)
@@ -175,10 +175,10 @@ sub _handle_error {
 }
 
 # List of abstract methods we are checking the derived class implements
-our @_abstract_methods = qw(new sql_regexp sql_not_regexp sql_limit
-                            sql_to_days sql_date_format sql_interval
-                            bz_lock_tables bz_unlock_tables
-                            REQUIRED_VERSION PROGRAM_NAME);
+our @_abstract_methods = qw(REQUIRED_VERSION PROGRAM_NAME
+                            new sql_regexp sql_not_regexp sql_limit sql_to_days
+                            sql_date_format sql_interval
+                            bz_lock_tables bz_unlock_tables);
 
 # This overriden import method will check implementation of inherited classes
 # for missing implementation of abstract methods
@@ -215,6 +215,35 @@ sub sql_position {
 # General Info Methods
 #####################################################################
 
+sub sql_string_concat {
+    my ($self, @params) = @_;
+    
+    return join(' || ', @params);
+}
+
+sub sql_fulltext_search {
+    my ($self, $column, $text) = @_;
+
+    # 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$/);
+
+    # make the string lowercase to do case insensitive search
+    my $lower_text = lc($text);
+
+    # split the text we search for to 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";
+}
+
 # XXX - Needs to be documented.
 sub bz_server_version {
     my ($self) = @_;
@@ -714,6 +743,26 @@ formatted SQL command have prefix C<sql_>. All other methods have prefix C<bz_>.
               $text = the text to search (scalar)
  Returns:     formatted SQL for substring search (scalar)
 
+=item C<sql_string_concat>
+
+ Description: Returns SQL syntax for concatenating multiple strings (constants
+              or values from table columns) together.
+ Params:      @params = array of column names or strings to concatenate
+ Returns:     formatted SQL for concatenating specified strings
+
+=item C<sql_fulltext_search>
+
+ Description: Returns SQL syntax for performing a full text search for
+              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
+              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
+
 =item C<bz_lock_tables>
 
  Description: Performs a table lock operation on specified tables.
index ae24d13bc82b009d5d63909a3f9cce5f9f876610..76cd0966d97e80d737f09aaa17b40e43a86f3d6a 100644 (file)
@@ -88,7 +88,7 @@ sub sql_not_regexp {
 }
 
 sub sql_limit {
-    my ($self, $limit,$offset) = @_;
+    my ($self, $limit, $offset) = @_;
 
     if (defined($offset)) {
         return "LIMIT $offset, $limit";
@@ -97,6 +97,18 @@ sub sql_limit {
     }
 }
 
+sub sql_string_concat {
+    my ($self, @params) = @_;
+    
+    return 'CONCAT(' . join(', ', @params) . ')';
+}
+
+sub sql_fulltext_search {
+    my ($self, $column, $text) = @_;
+
+    return "MATCH($column) AGAINST($text)";
+}
+
 sub sql_to_days {
     my ($self, $date) = @_;
 
index 9766da383ae2cf9b5ef624e6fdd7926723cab05d..5963f530803c4d7309fc059a65877ea6897c82b9 100644 (file)
@@ -93,7 +93,7 @@ sub sql_not_regexp {
 }
 
 sub sql_limit {
-    my ($self, $limit,$offset) = @_;
+    my ($self, $limit, $offset) = @_;
 
     if (defined($offset)) {
         return "LIMIT $limit OFFSET $offset";
@@ -131,6 +131,15 @@ sub sql_interval {
     return "INTERVAL '$interval'";
 }
 
+sub sql_string_concat {
+    my ($self, @params) = @_;
+    
+    # Postgres 7.3 does not support concatenating of different types, so we
+    # need to cast both parameters to text. Version 7.4 seems to handle this
+    # properly, so when we stop support 7.3, this can be removed.
+    return 'CAST(' . join(' AS text) || CAST(', @params) . ' AS text)';
+}
+
 sub bz_lock_tables {
     my ($self, @tables) = @_;
    
index 775778a9d53fccb961cd2142032f7f14ad888393..c38d070540f740730ffae37e88570f265c56f1d0 100644 (file)
@@ -545,14 +545,14 @@ sub init {
              # "content" is an alias for columns containing text for which we
              # can search a full-text index and retrieve results by relevance, 
              # currently just bug comments (and summaries to some degree).
-             # There's only one way to search a full-text index
-             # ("MATCH (...) AGAINST (...)"), so we only accept the "matches"
-             # operator, which is specific to full-text index searches.
+             # There's only one way to search a full-text index, so we only
+             # accept the "matches" operator, which is specific to full-text
+             # index searches.
 
              # Add the longdescs table to the query so we can search comments.
              my $table = "longdescs_$chartid";
-             push(@supptables, "INNER JOIN longdescs $table ON bugs.bug_id " . 
-                               "= $table.bug_id");
+             push(@supptables, "INNER JOIN longdescs AS $table " .
+                               "ON bugs.bug_id = $table.bug_id");
              if (Param("insidergroup") 
                  && !&::UserInGroup(Param("insidergroup")))
              {
@@ -563,11 +563,13 @@ sub init {
              # $term1 searches comments.
              # $term2 searches summaries, which contributes to the relevance
              # ranking in SELECT but doesn't limit which bugs get retrieved.
-             my $term1 = "MATCH($table.thetext) AGAINST(".&::SqlQuote($v).")";
-             my $term2 = "MATCH(bugs.short_desc) AGAINST(".&::SqlQuote($v).")";
+             my $term1 = $dbh->sql_fulltext_search("${table}.thetext",
+                                                   ::SqlQuote($v));
+             my $term2 = $dbh->sql_fulltext_search("bugs.short_desc",
+                                                   ::SqlQuote($v));
 
              # The term to use in the WHERE clause.
-             $term = $term1;
+             $term = "$term1 > 0";
 
              # In order to sort by relevance (in case the user requests it),
              # we SELECT the relevance value and give it an alias so we can
@@ -770,9 +772,11 @@ sub init {
              push(@supptables, "LEFT JOIN flagtypes $flagtypes " . 
                                "ON $flags.type_id = $flagtypes.id");
              
-             # Generate the condition by running the operator-specific function.
-             # Afterwards the condition resides in the global $term variable.
-             $ff = "CONCAT($flagtypes.name, $flags.status)";
+             # Generate the condition by running the operator-specific
+             # function. Afterwards the condition resides in the global $term
+             # variable.
+             $ff = $dbh->sql_string_concat("${flagtypes}.name",
+                                           "$flags.status");
              &{$funcsbykey{",$t"}};
              
              # If this is a negative condition (f.e. flag isn't "review+"),