[Rt-commit] rt branch, 4.0/fts-mysql-multiple-queries, updated. rt-4.0.4-282-g97e4fed

? sunnavy sunnavy at bestpractical.com
Thu Feb 9 05:41:11 EST 2012


The branch, 4.0/fts-mysql-multiple-queries has been updated
       via  97e4fed09b396885e5b9db461f8ea50cb78b8265 (commit)
      from  63582c77233510e54e34e865aeb78646c11e6783 (commit)

Summary of changes:
 lib/RT/Tickets.pm     |    9 ++++---
 lib/RT/Tickets_SQL.pm |   60 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 5 deletions(-)

- Log -----------------------------------------------------------------
commit 97e4fed09b396885e5b9db461f8ea50cb78b8265
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Feb 9 18:31:08 2012 +0800

    support continuous "content like ..." queries for mysql+sphinx
    
    by combining them into one query="..." in sphinx's boolean mode

diff --git a/lib/RT/Tickets.pm b/lib/RT/Tickets.pm
index 7ed43f7..89657a4 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -844,12 +844,13 @@ sub _TransContentLimit {
             $value =~ s/;/\\;/g;
 
             my $max = $config->{'MaxMatches'};
+            my $mode = $self->{_sql_sphinx_mode} || 'all';
             $self->_SQLLimit(
                 %rest,
-                ALIAS       => $alias,
-                FIELD       => 'query',
-                OPERATOR    => '=',
-                VALUE       => "$value;limit=$max;maxmatches=$max",
+                ALIAS    => $alias,
+                FIELD    => 'query',
+                OPERATOR => '=',
+                VALUE    => "$value;limit=$max;maxmatches=$max;mode=$mode",
             );
         }
     } else {
diff --git a/lib/RT/Tickets_SQL.pm b/lib/RT/Tickets_SQL.pm
index ec1bb49..ec51775 100644
--- a/lib/RT/Tickets_SQL.pm
+++ b/lib/RT/Tickets_SQL.pm
@@ -53,6 +53,7 @@ use warnings;
 
 
 use RT::SQL;
+use Regexp::Common qw/delimited/;
 
 # Import configuration data from the lexcial scope of __PACKAGE__ (or
 # at least where those two Subroutines are defined.)
@@ -291,8 +292,65 @@ sub FromSQL {
     $self->_InitSQL();
 
     return (1, $self->loc("No Query")) unless $query;
-
     $self->{_sql_query} = $query;
+
+
+    my $config = RT->Config->Get('FullTextSearch') || {};
+    if ( $config->{Indexed} && RT->Config->Get('DatabaseType') eq 'mysql' ) {
+
+# mysql doesn't bother asking sphinx if there are different query clauses.
+# I guess it's because mysql thinks there can't be a field who can meet
+# both "query='foo'' and "query='bar'", so it returns empty set directly.
+# that's why we combine those query into one here.
+# currently only continuous content queries are supported.
+
+        my $re_delim = $RE{delimited}{ -delim => qq{\'\"} };
+        my $re_content = '(?:^|\s+)Content\s+(?:(NOT)\s+)?LIKE\s+(' . $re_delim . ')';
+        my $first_escaped;
+        while ( $query =~ /($re_content\s+(AND|OR)\s*$re_content)/i ) {
+            my $whole      = $1;
+            my $first_neg  = $2;
+            my $first      = $3;
+            my $rel        = $4;
+            my $second_neg = $5;
+            my $second     = $6;
+            $rel = $rel =~ /and/i ? '&' : '|';
+
+            my $first_quote = substr $first, 0, 1;
+            $first =~ s!^$first_quote!!;
+            $first =~ s!$first_quote$!!;
+
+            if ( !$first_escaped ) {
+                $first =~ s/(&|\||!|-|\(|\))/\\$1/g;
+                $first = "!($first)" if $first_neg;
+            }
+
+            # we will quote value with '
+            $first =~ s!'!\\'!g if $first_quote eq '"';
+
+            my $second_quote = substr $second, 0, 1;
+            $second =~ s!^$second_quote!!;
+            $second =~ s!$second_quote$!!;
+            $second =~ s/(&|\||!|-|\(|\))/\\$1/g;
+            $second = "!($second)" if $second_neg;
+
+            # we will quote value with '
+            $second =~ s!'!\\'!g if $second_quote eq '"';
+
+            $query =~ s!\Q$whole!Content LIKE '($first$rel$second)'!;
+
+            $self->{_sql_sphinx_mode} = 'boolean';
+            $first_escaped = 1;
+        }
+
+        if ( $query =~ /$re_content.*$re_content/s ) {
+            return (0, $self->loc("Incontinuous Content queries"));
+        }
+        elsif ( $query =~ /$re_content/ && $1 ) {
+            return (0, $self->loc("Single NOT operator is not supported"));
+        }
+    }
+
     eval { $self->_parser( $query ); };
     if ( $@ ) {
         $RT::Logger->error( $@ );

-----------------------------------------------------------------------


More information about the Rt-commit mailing list