Merge pull request #45841 from 3nids/fix-rel-mismatch-type

improve success of compiled expressions running on backend with mismatching types in relation field pairs
This commit is contained in:
Denis Rouzaud 2021-11-09 09:30:36 +01:00 committed by GitHub
commit ac63c6e645
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 6 deletions

View File

@ -673,13 +673,14 @@ length, and presents text representations of non numeric/text types (e.g., geome
.. versionadded:: 2.14
%End
static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value );
static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value, QVariant::Type fieldType = QVariant::Type::Invalid );
%Docstring
Create an expression allowing to evaluate if a field is equal to a
value. The value may be null.
:param fieldName: the name of the field
:param value: the value of the field
:param fieldType: the type of the field on the left side used to quote the value. If not given, the value type is used instead
:return: the expression to evaluate field equality

View File

@ -1112,14 +1112,16 @@ QString QgsExpression::formatPreviewString( const QVariant &value, const bool ht
}
}
QString QgsExpression::createFieldEqualityExpression( const QString &fieldName, const QVariant &value )
QString QgsExpression::createFieldEqualityExpression( const QString &fieldName, const QVariant &value, QVariant::Type fieldType )
{
QString expr;
if ( value.isNull() )
expr = QStringLiteral( "%1 IS NULL" ).arg( quotedColumnRef( fieldName ) );
else
else if ( fieldType == QVariant::Type::Invalid )
expr = QStringLiteral( "%1 = %2" ).arg( quotedColumnRef( fieldName ), quotedValue( value ) );
else
expr = QStringLiteral( "%1 = %2" ).arg( quotedColumnRef( fieldName ), quotedValue( value, fieldType ) );
return expr;
}

View File

@ -659,10 +659,11 @@ class CORE_EXPORT QgsExpression
* value. The value may be null.
* \param fieldName the name of the field
* \param value the value of the field
* \param fieldType the type of the field on the left side used to quote the value. If not given, the value type is used instead
* \returns the expression to evaluate field equality
* \since QGIS 3.0
*/
static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value );
static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value, QVariant::Type fieldType = QVariant::Type::Invalid );
/**
* Returns TRUE if the given \a expression is a simple "field=value" type expression.

View File

@ -221,7 +221,16 @@ QString QgsRelation::getRelatedFeaturesFilter( const QgsFeature &feature ) const
for ( const FieldPair &pair : std::as_const( d->mFieldPairs ) )
{
QVariant val( feature.attribute( pair.referencedField() ) );
conditions << QgsExpression::createFieldEqualityExpression( pair.referencingField(), val );
int referencingIdx = referencingLayer()->fields().lookupField( pair.referencingField() );
if ( referencingIdx >= 0 )
{
QVariant::Type fieldType = referencingLayer()->fields().at( referencingIdx ).type();
conditions << QgsExpression::createFieldEqualityExpression( pair.referencingField(), val, fieldType );
}
else
{
conditions << QgsExpression::createFieldEqualityExpression( pair.referencingField(), val );
}
}
return conditions.join( QLatin1String( " AND " ) );
@ -233,8 +242,17 @@ QgsFeatureRequest QgsRelation::getReferencedFeatureRequest( const QgsAttributes
for ( const FieldPair &pair : std::as_const( d->mFieldPairs ) )
{
int referencedIdx = referencedLayer()->fields().lookupField( pair.referencedField() );
int referencingIdx = referencingLayer()->fields().lookupField( pair.referencingField() );
conditions << QgsExpression::createFieldEqualityExpression( pair.referencedField(), attributes.at( referencingIdx ) );
if ( referencedIdx >= 0 )
{
QVariant::Type fieldType = referencedLayer()->fields().at( referencedIdx ).type();
conditions << QgsExpression::createFieldEqualityExpression( pair.referencedField(), attributes.at( referencingIdx ), fieldType );
}
else
{
conditions << QgsExpression::createFieldEqualityExpression( pair.referencedField(), attributes.at( referencingIdx ) );
}
}
QgsFeatureRequest myRequest;

View File

@ -271,6 +271,20 @@ class TestQgsExpressionCustomFunctions(unittest.TestCase):
res = '"my\'field" = TRUE'
self.assertEqual(e.createFieldEqualityExpression(field, value), res)
# test with field type
field = "myfield"
value = 1
type = QVariant.String
res = '"myfield" = \'1\''
self.assertEqual(e.createFieldEqualityExpression(field, value, type), res)
# test with field type
field = "myfield"
value = "1"
type = QVariant.Int
res = '"myfield" = 1'
self.assertEqual(e.createFieldEqualityExpression(field, value, type), res)
def testReferencedAttributeIndexesNonExistingField(self):
e = QgsExpression()
e.setExpression("foo = 1")