Merge pull request #58559 from elpaso/bugfix-gh52219-relation-ref-not-null-followup

Fix default AllowNotNULL for relation ref wdgt
This commit is contained in:
Alessandro Pasotti 2024-09-04 07:34:54 +02:00 committed by GitHub
commit fac763d385
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 72 additions and 13 deletions

View File

@ -262,6 +262,13 @@ Returns a list of attributes used to form the referencing fields
(foreign key) on the referencing (child) layer.
:return: A list of attributes
%End
bool referencingFieldsAllowNull() const;
%Docstring
Returns ``True`` if none of the referencing fields has a NOT NULL constraint.
.. versionadded:: 3.28
%End
bool isValid() const;

View File

@ -262,6 +262,13 @@ Returns a list of attributes used to form the referencing fields
(foreign key) on the referencing (child) layer.
:return: A list of attributes
%End
bool referencingFieldsAllowNull() const;
%Docstring
Returns ``True`` if none of the referencing fields has a NOT NULL constraint.
.. versionadded:: 3.28
%End
bool isValid() const;

View File

@ -356,6 +356,26 @@ QgsAttributeList QgsRelation::referencingFields() const
}
bool QgsRelation::referencingFieldsAllowNull() const
{
if ( ! referencingLayer() )
{
return false;
}
const auto fields = referencingFields();
return std::find_if( fields.constBegin(), fields.constEnd(), [&]( const auto & fieldIdx )
{
if ( !referencingLayer()->fields().exists( fieldIdx ) )
{
return false;
}
const QgsField field = referencingLayer()->fields().field( fieldIdx );
return field.constraints().constraints().testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull );
} ) == fields.constEnd();
}
bool QgsRelation::isValid() const
{
return d->mValid && !d->mReferencingLayer.isNull() && !d->mReferencedLayer.isNull() && d->mReferencingLayer.data()->isValid() && d->mReferencedLayer.data()->isValid();

View File

@ -332,6 +332,12 @@ class CORE_EXPORT QgsRelation
*/
QgsAttributeList referencingFields() const;
/**
* Returns TRUE if none of the referencing fields has a NOT NULL constraint.
* \since QGIS 3.28
*/
bool referencingFieldsAllowNull() const;
/**
* Returns the validity of this relation. Don't use the information if it's not valid.
* A relation is considered valid if both referenced and referencig layers are valid.

View File

@ -151,20 +151,11 @@ void QgsRelationReferenceConfigDlg::relationChanged( int idx )
mCbxMapIdentification->setEnabled( mReferencedLayer->isSpatial() );
}
// Provide a default for AllowNull if it was not set by the config
// If AllowNULL is not set in the config, provide a default value based on the
// constraints of the referencing fields
if ( ! mAllowNullWasSetByConfig )
{
const QgsAttributeList referencingFields = rel.referencingFields();
const bool allowNull { std::find_if( referencingFields.constBegin(), referencingFields.constEnd(), [&]( const auto & fieldIdx )
{
if ( !rel.referencingLayer()->fields().exists( fieldIdx ) )
{
return false;
}
const QgsField field = rel.referencingLayer()->fields().field( fieldIdx );
return field.constraints().constraints().testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull );
} ) == referencingFields.constEnd()};
mCbxAllowNull->setChecked( allowNull );
mCbxAllowNull->setChecked( rel.referencingFieldsAllowNull() );
}
loadFields();

View File

@ -105,7 +105,16 @@ void QgsRelationReferenceWidgetWrapper::initWidget( QWidget *editor )
}
while ( ctx );
mWidget->setRelation( relation, config( QStringLiteral( "AllowNULL" ) ).toBool() );
// If AllowNULL is not set in the config, provide a default value based on the
// constraints of the referencing fields
if ( !config( QStringLiteral( "AllowNULL" ) ).isValid() )
{
mWidget->setRelation( relation, relation.referencingFieldsAllowNull() );
}
else
{
mWidget->setRelation( relation, config( QStringLiteral( "AllowNULL" ) ).toBool() );
}
connect( mWidget, &QgsRelationReferenceWidget::foreignKeysChanged, this, &QgsRelationReferenceWidgetWrapper::foreignKeysChanged );
}

View File

@ -19,6 +19,7 @@ from qgis.core import (
QgsProject,
QgsRelation,
QgsVectorLayer,
QgsFieldConstraints,
)
import unittest
from qgis.testing import start_app, QgisTestCase
@ -250,6 +251,24 @@ class TestQgsRelation(QgisTestCase):
# Check that it does not crash
rel.generateId()
def test_referencingFieldsAllowNull(self):
rel = QgsRelation()
rel.setId('rel1')
rel.setName('Relation Number One')
rel.setReferencingLayer(self.referencingLayer.id())
rel.setReferencedLayer(self.referencedLayer.id())
rel.addFieldPair('foreignkey', 'y')
self.assertTrue(rel.referencingFieldsAllowNull())
referencingLayer = rel.referencingLayer()
# Set Not Null constraint on the field
referencingLayer.setFieldConstraint(referencingLayer.fields().indexFromName('foreignkey'), QgsFieldConstraints.ConstraintNotNull)
self.assertFalse(rel.referencingFieldsAllowNull())
if __name__ == '__main__':
unittest.main()