Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/filter/filtercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,11 @@ QString FilterController::buildFieldExpression( const FieldFilter &filter ) cons
QString textValue = QgsExpression::quotedString( filter.value.toList().at( 0 ).toString() );
// remove single quotes from the beginning and end of returned string
textValue = textValue.slice( 1, textValue.size() - 2 );
textValue.replace( QStringLiteral( "!" ), QStringLiteral( "!!" ) );
textValue.replace( QStringLiteral( "%" ), QStringLiteral( "!%" ) );
textValue.replace( QStringLiteral( "_" ), QStringLiteral( "!_" ) );
expressionCopy.replace( QStringLiteral( "@@value@@" ), textValue );
expressionCopy.append( QStringLiteral( " ESCAPE '!'" ) );
Comment on lines +237 to +241

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create new function in InputUtils which will do these steps and just call it from here. Use backslash as the escape character instead. Also are these all the wildcards you can get?

break;
}
case FieldFilter::CheckboxFilter:
Expand Down
66 changes: 65 additions & 1 deletion app/test/testfiltercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#include <QtTest/QtTest>
#include <QDateTime>
#include <QFile>
#include <QTemporaryDir>

#include <qgsproject.h>
#include <qgsvectorlayer.h>
Expand Down Expand Up @@ -554,11 +556,73 @@ void TestFilterController::testTextFilter()
filterValues[filterId] = QVariantList{ QStringLiteral( "great" ) };
mController->processFilters( filterValues );

const QString expected = QStringLiteral( "(\"Condition\" LIKE '%great%')" );
const QString expected = QStringLiteral( "(\"Condition\" LIKE '%great%' ESCAPE '!')" );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are not escaping anything here

QCOMPARE( layer->subsetString(), expected );
QCOMPARE( layer->featureCount(), ( long long ) 14 );
}

void TestFilterController::testTextFilterWildcards_data()
{
QTest::addColumn<QString>( "searchValue" );
QTest::addColumn<QString>( "expectedPattern" );
QTest::addColumn<qlonglong>( "expectedCount" );

QTest::newRow( "percent" ) << QStringLiteral( "%" ) << QStringLiteral( "%!%%" ) << 2LL;
QTest::newRow( "underscore" ) << QStringLiteral( "_" ) << QStringLiteral( "%!_%" ) << 2LL;
QTest::newRow( "escape-character" ) << QStringLiteral( "!" ) << QStringLiteral( "%!!%" ) << 1LL;
QTest::newRow( "combined-wildcards" ) << QStringLiteral( "%_" ) << QStringLiteral( "%!%!_%" ) << 1LL;
}
Comment on lines +564 to +574

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use this, just use the expected values inline


void TestFilterController::testTextFilterWildcards()
{
QFETCH( QString, searchValue );
QFETCH( QString, expectedPattern );
QFETCH( qlonglong, expectedCount );

QTemporaryDir tempDir;
QVERIFY( tempDir.isValid() );
const QString layerPath = tempDir.filePath( QStringLiteral( "roads.gpkg" ) );
QVERIFY( QFile::copy( TestUtils::testDataDir() + QStringLiteral( "/filtering/roads.gpkg" ), layerPath ) );

const QString fieldName = QStringLiteral( "Condition" );
QgsVectorLayer *layer = new QgsVectorLayer(
layerPath + QStringLiteral( "|layername=roads" ),
QStringLiteral( "text-filter-wildcards" ),
QStringLiteral( "ogr" )
);
QVERIFY( layer );
QVERIFY( layer->isValid() );
QgsProject::instance()->addMapLayer( layer );
Comment on lines +582 to +595

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with the approach in other tests?


const QStringList values =
{
QStringLiteral( "plain" ),
QStringLiteral( "percent%only" ),
QStringLiteral( "under_score" ),
QStringLiteral( "bang!mark" ),
QStringLiteral( "both%_chars" )
};
Comment on lines +597 to +604

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use values that could match values in condition

for ( const QString &value : values )
{
QVERIFY( TestUtils::addFeatureToLayer( layer, fieldName, value ) );
}
Comment on lines +605 to +608

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't add more features to the layer there already are some, use them


const QString sql = QStringLiteral( "\"Condition\" LIKE '%@@value@@%'" );
const QString filterId = TestUtils::setupControllerWithFilter(
mController.get(), FieldFilter::TextFilter, layer->id(), fieldName, sql );
QVERIFY( !filterId.isEmpty() );

QVariantMap filterValues;
filterValues[filterId] = QVariantList{ searchValue };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply the filter values one by one and check the results after each one

mController->processFilters( filterValues );

const QString expected = QStringLiteral( "(\"Condition\" LIKE '%1' ESCAPE '!')" ).arg( expectedPattern );
QCOMPARE( layer->subsetString(), expected );
QCOMPARE( layer->featureCount(), expectedCount );

QgsProject::instance()->removeMapLayer( layer );
}

// Checkbox filter
void TestFilterController::testCheckboxFilter()
{
Expand Down
2 changes: 2 additions & 0 deletions app/test/testfiltercontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class TestFilterController : public QObject

// Text filter
void testTextFilter();
void testTextFilterWildcards_data();
void testTextFilterWildcards();

// Checkbox filter
void testCheckboxFilter();
Expand Down