From bce33fe8a423ca0fbef395606340f545c497621a Mon Sep 17 00:00:00 2001 From: sunnavy Date: Wed, 24 Jan 2024 16:33:14 -0500 Subject: [PATCH] Add more fulltext search tests for the new split feature --- t/fts/indexed_mysql.t | 67 ++++++++++++++++++++++++++++++++++++++++- t/fts/indexed_oracle.t | 68 ++++++++++++++++++++++++++++++++++++++++-- t/fts/indexed_pg.t | 67 ++++++++++++++++++++++++++++++++++++++++- t/fts/not_indexed.t | 67 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 263 insertions(+), 6 deletions(-) diff --git a/t/fts/indexed_mysql.t b/t/fts/indexed_mysql.t index 672b220723d..4ce8d83efb0 100644 --- a/t/fts/indexed_mysql.t +++ b/t/fts/indexed_mysql.t @@ -66,7 +66,7 @@ sub run_test { @tickets = RT::Test->create_tickets( { Queue => $q->id }, - { Subject => 'first', Content => 'english' }, + { Subject => 'first', Content => 'english american' }, { Subject => 'second', Content => 'french' }, { Subject => 'third', Content => 'spanish' }, { Subject => 'fourth', Content => 'german' }, @@ -76,8 +76,73 @@ sync_index(); run_tests( "Content LIKE 'english'" => { first => 1, second => 0, third => 0, fourth => 0 }, "Content LIKE 'french'" => { first => 0, second => 1, third => 0, fourth => 0 }, + "Subject LIKE 'first' OR Content LIKE 'french'" => { first => 1, second => 1, third => 0, fourth => 0 }, + "Content LIKE 'english' AND Content LIKE 'american'" => { first => 1, second => 0, third => 0, fourth => 0 }, ); +my ( $ret, $msg ) = $tickets[0]->Correspond( Content => 'chinese' ); +ok( $ret, 'Corresponded' ) or diag $msg; + +( $ret, $msg ) = $tickets[0]->SetSubject('updated'); +ok( $ret, 'Updated subject' ) or diag $msg; + +sync_index(); + +run_tests( + "Content LIKE 'english' AND Content LIKE 'chinese'" => { updated => 1, second => 0, third => 0, fourth => 0 }, + "Subject LIKE 'updated' OR Content LIKE 'french'" => { updated => 1, second => 1, third => 0, fourth => 0 }, + "( Subject LIKE 'updated' OR Content LIKE 'english' ) AND ( Content LIKE 'french' OR Content LIKE 'chinese' )" + => { updated => 1, second => 0, third => 0, fourth => 0 }, +); + +diag "Checking SQL query"; + +my $tickets = RT::Tickets->new( RT->SystemUser ); +$tickets->FromSQL(q{Content LIKE 'english' AND Content LIKE 'chinese'}); +like( $tickets->BuildSelectQuery(), qr{ INTERSECT }, 'AND query contains INTERSECT' ); + +$tickets->FromSQL(q{Subject LIKE 'updated' OR Content LIKE 'french'}); +like( $tickets->BuildSelectQuery(), qr{ UNION }, 'OR query contains UNION' ); + +$tickets->FromSQL( + q{(Subject LIKE 'updated' OR Content LIKE 'english') AND ( Content LIKE 'french' OR Content LIKE 'chinese' )}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR query contains both INTERSECT and UNION' +); + +diag "Checking transaction searches"; + +my $txns = RT::Transactions->new( RT->SystemUser ); +$txns->FromSQL(q{Content LIKE 'english' AND Content LIKE 'american'}); +is( $txns->Count, 1, 'Found one transaction' ); +my $txn = $txns->First; +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +like( $txn->Content, qr/english american/, 'Transaction content' ); + +$txns->FromSQL(q{Content LIKE 'english' AND Content LIKE 'chinese'}); +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +is( $txns->Count, 0, 'Found 0 transactions' ); + +$txns->FromSQL(q{Content LIKE 'english' OR Content LIKE 'chinese'}); +like( $txns->BuildSelectQuery(), qr{ UNION }, 'OR transaction query contains UNION' ); +is( $txns->Count, 2, 'Found 2 transactions' ); +my @txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/english/, 'Transaction content' ); +like( $txns[1]->Content, qr/chinese/, 'Transaction content' ); + +$txns->FromSQL(q{( Content LIKE 'english' AND Content LIKE 'american' ) OR Content LIKE 'chinese'}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR transaction query contains both INTERSECT and UNION' +); +is( $txns->Count, 2, 'Found 2 transactions' ); +@txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/english/, 'Transaction content' ); +like( $txns[1]->Content, qr/chinese/, 'Transaction content' ); + @tickets = (); done_testing; diff --git a/t/fts/indexed_oracle.t b/t/fts/indexed_oracle.t index a5b15bd825e..9ac7f80a264 100644 --- a/t/fts/indexed_oracle.t +++ b/t/fts/indexed_oracle.t @@ -4,7 +4,6 @@ use warnings; use RT::Test tests => undef; plan skip_all => 'Not Oracle' unless RT->Config->Get('DatabaseType') eq 'Oracle'; -plan tests => 13; RT->Config->Set( FullTextSearch => Enable => 1, Indexed => 1, IndexName => 'rt_fts_index' ); @@ -67,7 +66,7 @@ sub run_test { @tickets = RT::Test->create_tickets( { Queue => $q->id }, - { Subject => 'book', Content => 'book' }, + { Subject => 'book', Content => 'book initial' }, { Subject => 'bar', Content => 'bar' }, ); sync_index(); @@ -77,5 +76,70 @@ run_tests( "Content LIKE 'bar'" => { book => 0, bar => 1 }, ); +my $book = $tickets[0]; +my ( $ret, $msg ) = $book->Correspond( Content => 'hobbit' ); +ok( $ret, 'Corresponded' ) or diag $msg; + +( $ret, $msg ) = $book->SetSubject('updated'); +ok( $ret, 'Updated subject' ) or diag $msg; + +sync_index(); + +run_tests( + "Content LIKE 'book' AND Content LIKE 'hobbit'" => { updated => 1, bar => 0 }, + "Subject LIKE 'updated' OR Content LIKE 'bar'" => { updated => 1, bar => 1 }, + "( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bar' )" => + { updated => 1, bar => 0 }, +); + +diag "Checking SQL query"; + +my $tickets = RT::Tickets->new( RT->SystemUser ); +$tickets->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +like( $tickets->BuildSelectQuery(), qr{ INTERSECT }, 'AND query contains INTERSECT' ); + +$tickets->FromSQL(q{Subject LIKE 'updated' OR Content LIKE 'bar'}); +like( $tickets->BuildSelectQuery(), qr{ UNION }, 'OR query contains UNION' ); + +$tickets->FromSQL( + q{( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bar' )}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR query contains both INTERSECT and UNION' +); + +diag "Checking transaction searches"; + +my $txns = RT::Transactions->new( RT->SystemUser ); +$txns->FromSQL(qq{Content LIKE 'book' AND Content LIKE 'initial'}); +is( $txns->Count, 1, 'Found one transaction' ); +my $txn = $txns->First; +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +like( $txn->Content, qr/book initial/, 'Transaction content' ); + +$txns->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +is( $txns->Count, 0, 'Found 0 transactions' ); + +$txns->FromSQL(q{Content LIKE 'book' OR Content LIKE 'hobbit'}); +like( $txns->BuildSelectQuery(), qr{ UNION }, 'OR transaction query contains UNION' ); +is( $txns->Count, 2, 'Found 2 transactions' ); +my @txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + +$txns->FromSQL(qq{( Content LIKE 'book' AND Content LIKE 'initial' ) OR Content LIKE 'hobbit'}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR transaction query contains both INTERSECT and UNION' +); +is( $txns->Count, 2, 'Found 2 transactions' ); +@txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + @tickets = (); +done_testing; diff --git a/t/fts/indexed_pg.t b/t/fts/indexed_pg.t index 1494fded25b..a81c9b2c3dd 100644 --- a/t/fts/indexed_pg.t +++ b/t/fts/indexed_pg.t @@ -97,7 +97,72 @@ run_tests( "Content LIKE 'pubs'" => { $book->id => 0, $bars->id => 0 }, ); -# Test the "ts_vector too long" skip +my ( $ret, $msg ) = $book->Correspond( Content => 'hobbit' ); +ok( $ret, 'Corresponded' ) or diag $msg; + +( $ret, $msg ) = $book->SetSubject('updated'); +ok( $ret, 'Updated subject' ) or diag $msg; + +sync_index(); + +run_tests( + "Content LIKE 'book' AND Content LIKE 'hobbit'" => { $book->id => 1, $bars->id => 0 }, + "Subject LIKE 'updated' OR Content LIKE 'bars'" => { $book->id => 1, $bars->id => 1 }, + "( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bars' )" => + { $book->id => 1, $bars->id => 0 }, +); + +diag "Checking SQL query"; + +my $tickets = RT::Tickets->new( RT->SystemUser ); +$tickets->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +like( $tickets->BuildSelectQuery(), qr{ INTERSECT }, 'AND query contains INTERSECT' ); + +$tickets->FromSQL(q{Subject LIKE 'updated' OR Content LIKE 'bars'}); +like( $tickets->BuildSelectQuery(), qr{ UNION }, 'OR query contains UNION' ); + +$tickets->FromSQL( + q{( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bars' )}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR query contains both INTERSECT and UNION' +); + +diag "Checking transaction searches"; + +my $txns = RT::Transactions->new( RT->SystemUser ); +$txns->FromSQL(qq{Content LIKE 'book' AND Content LIKE '$blase'}); +is( $txns->Count, 1, 'Found one transaction' ); +my $txn = $txns->First; +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +like( $txn->Content, qr/book $blase/, 'Transaction content' ); + +$txns->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +like( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query contains INTERSECT' ); +is( $txns->Count, 0, 'Found 0 transactions' ); + +$txns->FromSQL(q{Content LIKE 'book' OR Content LIKE 'hobbit'}); +like( $txns->BuildSelectQuery(), qr{ UNION }, 'OR transaction query contains UNION' ); +is( $txns->Count, 2, 'Found 2 transactions' ); +my @txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + +$txns->FromSQL(qq{( Content LIKE 'book' AND Content LIKE '$blase' ) OR Content LIKE 'hobbit'}); +like( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR transaction query contains both INTERSECT and UNION' +); +is( $txns->Count, 2, 'Found 2 transactions' ); +@txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + + +diag q{Test the "ts_vector too long" skip}; + my $content = ""; $content .= "$_\n" for 1..200_000; @tickets = RT::Test->create_tickets( diff --git a/t/fts/not_indexed.t b/t/fts/not_indexed.t index 9ec77ebfbdd..c8333e4fa9a 100644 --- a/t/fts/not_indexed.t +++ b/t/fts/not_indexed.t @@ -2,7 +2,7 @@ use strict; use warnings; -use RT::Test tests => 20; +use RT::Test tests => undef; RT->Config->Set( FullTextSearch => Enable => 1, Indexed => 0 ); @@ -44,7 +44,7 @@ sub run_test { @tickets = RT::Test->create_tickets( { Queue => $q->id }, - { Subject => 'book', Content => 'book' }, + { Subject => 'book', Content => 'book initial' }, { Subject => 'bar', Content => 'bar' }, { Subject => 'no content', Content => undef }, ); @@ -57,4 +57,67 @@ run_tests( "(Content LIKE 'bar' OR Subject LIKE 'missing')" => { bar => 1 }, ); +my $book = $tickets[0]; +my ( $ret, $msg ) = $book->Correspond( Content => 'hobbit' ); +ok( $ret, 'Corresponded' ) or diag $msg; +( $ret, $msg ) = $book->SetSubject('updated'); +ok( $ret, 'Updated subject' ) or diag $msg; + +run_tests( + "Subject LIKE 'updated' OR Content LIKE 'bar'" => { updated => 1, bar => 1 }, + "( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bar' )" => + { updated => 1, bar => 0 }, +); + +diag "Checking SQL query"; + +my $tickets = RT::Tickets->new( RT->SystemUser ); +$tickets->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +unlike( $tickets->BuildSelectQuery(), qr{ INTERSECT }, 'AND query does not contain INTERSECT' ); + +$tickets->FromSQL(q{Subject LIKE 'updated' OR Content LIKE 'bar'}); +unlike( $tickets->BuildSelectQuery(), qr{ UNION }, 'OR query does not contain UNION' ); + +$tickets->FromSQL( + q{( Subject LIKE 'updated' OR Content LIKE 'hobbit' ) AND ( Content LIKE 'book' OR Content LIKE 'bar' )}); +unlike( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR query does not contain both INTERSECT and UNION' +); + +diag "Checking transaction searches"; + +my $txns = RT::Transactions->new( RT->SystemUser ); +$txns->FromSQL(qq{Content LIKE 'book' AND Content LIKE 'initial'}); +is( $txns->Count, 1, 'Found one transaction' ); +my $txn = $txns->First; +unlike( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query does not contain INTERSECT' ); +like( $txn->Content, qr/book initial/, 'Transaction content' ); + +$txns->FromSQL(q{Content LIKE 'book' AND Content LIKE 'hobbit'}); +unlike( $txns->BuildSelectQuery(), qr{ INTERSECT }, 'AND transaction query does not contain INTERSECT' ); +is( $txns->Count, 0, 'Found 0 transactions' ); + +$txns->FromSQL(q{Content LIKE 'book' OR Content LIKE 'hobbit'}); +unlike( $txns->BuildSelectQuery(), qr{ UNION }, 'OR transaction query does not contain UNION' ); +is( $txns->Count, 2, 'Found 2 transactions' ); +my @txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + +$txns->FromSQL(qq{( Content LIKE 'book' AND Content LIKE 'initial' ) OR Content LIKE 'hobbit'}); +unlike( + $tickets->BuildSelectQuery(), + qr{ (?:INTERSECT|UNION) .+ (?:INTERSECT|UNION) }, + 'AND&OR transaction query does not contain both INTERSECT and UNION' +); +is( $txns->Count, 2, 'Found 2 transactions' ); +@txns = @{ $txns->ItemsArrayRef }; +like( $txns[0]->Content, qr/book/, 'Transaction content' ); +like( $txns[1]->Content, qr/hobbit/, 'Transaction content' ); + +@tickets = (); + +done_testing;