Refactor constraint handling

- store constraint origin in QgsField
- move handling of constraint expressions to QgsField
This commit is contained in:
Nyall Dawson 2016-10-26 08:53:08 +10:00
parent 1cecf37b40
commit f99ea26bdf
19 changed files with 302 additions and 65 deletions

View File

@ -26,6 +26,17 @@ class QgsField
};
typedef QFlags<QgsField::Constraint> Constraints;
/**
* Origin of constraints.
* @note added in QGIS 3.0
*/
enum ConstraintOrigin
{
ConstraintOriginNotSet, //!< Constraint is not set
ConstraintOriginProvider, //!< Constraint was set at data provider
ConstraintOriginLayer, //!< Constraint was set by layer
};
/** Constructor. Constructs a new QgsField object.
* @param name Field name
* @param type Field variant type, currently supported: String / Int / Double
@ -178,15 +189,60 @@ class QgsField
* Returns any constraints which are present for the field.
* @note added in QGIS 3.0
* @see setConstraints()
* @see constraintOrigin()
*/
Constraints constraints() const;
/**
* Sets constraints which are present for the field.
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
* is not present on this field.
* @note added in QGIS 3.0
* @see constraints()
*/
void setConstraints( Constraints constraints );
ConstraintOrigin constraintOrigin( Constraint constraint ) const;
/**
* Sets a constraint on the field.
* @note added in QGIS 3.0
* @see constraints()
* @see removeConstraint()
*/
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );
/**
* Removes a constraint from the field.
* @see setConstraint()
* @see constraints()
*/
void removeConstraint( Constraint constraint );
/**
* Returns the constraint expression for the field, if set.
* @note added in QGIS 3.0
* @see constraints()
* @see constraintDescription()
* @see setConstraintExpression()
*/
QString constraintExpression() const;
/**
* Returns the descriptive name for the constraint expression.
* @note added in QGIS 3.0
* @see constraints()
* @see constraintExpression()
* @see setConstraintExpression()
*/
QString constraintDescription() const;
/**
* Set the constraint expression for the field. An optional descriptive name for the constraint
* can also be set. Setting an empty expression will clear any existing expression constraint.
* @note added in QGIS 3.0
* @see constraintExpression()
* @see constraintDescription()
* @see constraints()
*/
void setConstraintExpression( const QString& expression, const QString& description = QString() );
/** Returns the alias for the field (the friendly displayed name of the field ),
* or an empty string if there is no alias.

View File

@ -235,7 +235,7 @@ class QgsVectorDataProvider : QgsDataProvider
* field index.
* @note added in QGIS 3.0
*/
virtual QgsField::Constraints fieldConstraints( int fieldIndex ) const;
QgsField::Constraints fieldConstraints( int fieldIndex ) const;
/**
* Changes geometries of existing features

View File

@ -562,10 +562,12 @@ void QgsFieldsProperties::attributeTypeDialog()
attributeTypeDialog.setUnique( cfg.mConstraints & QgsField::ConstraintUnique );
QgsField::Constraints providerConstraints = 0;
if ( mLayer->fields().fieldOrigin( index ) == QgsFields::OriginProvider )
{
providerConstraints = mLayer->dataProvider()->fieldConstraints( mLayer->fields().fieldOriginIndex( index ) );
}
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintNotNull ) == QgsField::ConstraintOriginProvider )
providerConstraints |= QgsField::ConstraintNotNull;
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintUnique ) == QgsField::ConstraintOriginProvider )
providerConstraints |= QgsField::ConstraintUnique;
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintExpression ) == QgsField::ConstraintOriginProvider )
providerConstraints |= QgsField::ConstraintExpression;
attributeTypeDialog.setProviderConstraints( providerConstraints );
attributeTypeDialog.setConstraintExpression( cfg.mConstraint );
@ -1059,7 +1061,7 @@ QgsFieldsProperties::FieldConfig::FieldConfig( QgsVectorLayer* layer, int idx )
mEditableEnabled = layer->fields().fieldOrigin( idx ) != QgsFields::OriginJoin
&& layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression;
mLabelOnTop = layer->editFormConfig().labelOnTop( idx );
mConstraints = layer->fieldConstraints( idx );
mConstraints = layer->fields().at( idx ).constraints();
mConstraint = layer->editFormConfig().constraintExpression( idx );
mConstraintDescription = layer->editFormConfig().constraintDescription( idx );
const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( layer, layer->fields().field( idx ).name() );

View File

@ -185,9 +185,55 @@ QgsField::Constraints QgsField::constraints() const
return d->constraints;
}
void QgsField::setConstraints( Constraints constraints )
QgsField::ConstraintOrigin QgsField::constraintOrigin( QgsField::Constraint constraint ) const
{
d->constraints = constraints;
if ( !( d->constraints & constraint ) )
return ConstraintOriginNotSet;
return d->constraintOrigins.value( constraint, ConstraintOriginNotSet );
}
void QgsField::setConstraint( QgsField::Constraint constraint, QgsField::ConstraintOrigin origin )
{
if ( origin == ConstraintOriginNotSet )
{
d->constraints &= ~constraint;
d->constraintOrigins.remove( constraint );
}
else
{
d->constraints |= constraint;
d->constraintOrigins.insert( constraint, origin );
}
}
void QgsField::removeConstraint( QgsField::Constraint constraint )
{
d->constraints &= ~constraint;
}
QString QgsField::constraintExpression() const
{
return d->constraints & QgsField::ConstraintExpression ? d->expressionConstraint : QString();
}
QString QgsField::constraintDescription() const
{
return d->expressionConstraintDescription;
}
void QgsField::setConstraintExpression( const QString& expression, const QString& description )
{
if ( expression.isEmpty() )
d->constraints &= ~QgsField::ConstraintExpression;
else
{
d->constraints |= QgsField::ConstraintExpression;
d->constraintOrigins.insert( QgsField::ConstraintExpression, QgsField::ConstraintOriginLayer );
}
d->expressionConstraint = expression;
d->expressionConstraintDescription = description;
}
QString QgsField::alias() const
@ -314,15 +360,22 @@ QDataStream& operator<<( QDataStream& out, const QgsField& field )
out << field.alias();
out << field.defaultValueExpression();
out << field.constraints();
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintNotNull ) );
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintUnique ) );
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintExpression ) );
out << field.constraintExpression();
out << field.constraintDescription();
out << static_cast< quint32 >( field.subType() );
return out;
}
QDataStream& operator>>( QDataStream& in, QgsField& field )
{
quint32 type, subType, length, precision, constraints;
QString name, typeName, comment, alias, defaultValueExpression;
in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression >> constraints >> subType;
quint32 type, subType, length, precision, constraints, originNotNull, originUnique, originExpression;
QString name, typeName, comment, alias, defaultValueExpression, constraintExpression, constraintDescription;
in >> name >> type >> typeName >> length >> precision >> comment >> alias
>> defaultValueExpression >> constraints >> originNotNull >> originUnique >> originExpression >>
constraintExpression >> constraintDescription >> subType;
field.setName( name );
field.setType( static_cast< QVariant::Type >( type ) );
field.setTypeName( typeName );
@ -331,7 +384,19 @@ QDataStream& operator>>( QDataStream& in, QgsField& field )
field.setComment( comment );
field.setAlias( alias );
field.setDefaultValueExpression( defaultValueExpression );
field.setConstraints( static_cast< QgsField::Constraints>( constraints ) );
if ( constraints & QgsField::ConstraintNotNull )
field.setConstraint( QgsField::ConstraintNotNull, static_cast< QgsField::ConstraintOrigin>( originNotNull ) );
else
field.removeConstraint( QgsField::ConstraintNotNull );
if ( constraints & QgsField::ConstraintUnique )
field.setConstraint( QgsField::ConstraintUnique, static_cast< QgsField::ConstraintOrigin>( originUnique ) );
else
field.removeConstraint( QgsField::ConstraintUnique );
if ( constraints & QgsField::ConstraintExpression )
field.setConstraint( QgsField::ConstraintExpression, static_cast< QgsField::ConstraintOrigin>( originExpression ) );
else
field.removeConstraint( QgsField::ConstraintExpression );
field.setConstraintExpression( constraintExpression, constraintDescription );
field.setSubType( static_cast< QVariant::Type >( subType ) );
return in;
}

View File

@ -54,7 +54,7 @@ class CORE_EXPORT QgsField
Q_PROPERTY( QString name READ name WRITE setName )
Q_PROPERTY( QString alias READ alias WRITE setAlias )
Q_PROPERTY( QString defaultValueExpression READ defaultValueExpression WRITE setDefaultValueExpression )
Q_PROPERTY( Constraints constraints READ constraints WRITE setConstraints )
Q_PROPERTY( Constraints constraints READ constraints )
public:
@ -66,9 +66,21 @@ class CORE_EXPORT QgsField
{
ConstraintNotNull = 1, //!< Field may not be null
ConstraintUnique = 1 << 1, //!< Field must have a unique value
ConstraintExpression = 1 << 2, //!< Field has an expression constraint set. See constraintExpression().
};
Q_DECLARE_FLAGS( Constraints, Constraint )
/**
* Origin of constraints.
* @note added in QGIS 3.0
*/
enum ConstraintOrigin
{
ConstraintOriginNotSet = 0, //!< Constraint is not set
ConstraintOriginProvider, //!< Constraint was set at data provider
ConstraintOriginLayer, //!< Constraint was set by layer
};
/** Constructor. Constructs a new QgsField object.
* @param name Field name
* @param type Field variant type, currently supported: String / Int / Double
@ -225,15 +237,60 @@ class CORE_EXPORT QgsField
* Returns any constraints which are present for the field.
* @note added in QGIS 3.0
* @see setConstraints()
* @see constraintOrigin()
*/
Constraints constraints() const;
/**
* Sets constraints which are present for the field.
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
* is not present on this field.
* @note added in QGIS 3.0
* @see constraints()
*/
void setConstraints( Constraints constraints );
ConstraintOrigin constraintOrigin( Constraint constraint ) const;
/**
* Sets a constraint on the field.
* @note added in QGIS 3.0
* @see constraints()
* @see removeConstraint()
*/
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );
/**
* Removes a constraint from the field.
* @see setConstraint()
* @see constraints()
*/
void removeConstraint( Constraint constraint );
/**
* Returns the constraint expression for the field, if set.
* @note added in QGIS 3.0
* @see constraints()
* @see constraintDescription()
* @see setConstraintExpression()
*/
QString constraintExpression() const;
/**
* Returns the descriptive name for the constraint expression.
* @note added in QGIS 3.0
* @see constraints()
* @see constraintExpression()
* @see setConstraintExpression()
*/
QString constraintDescription() const;
/**
* Set the constraint expression for the field. An optional descriptive name for the constraint
* can also be set. Setting an empty expression will clear any existing expression constraint.
* @note added in QGIS 3.0
* @see constraintExpression()
* @see constraintDescription()
* @see constraints()
*/
void setConstraintExpression( const QString& expression, const QString& description = QString() );
/** Returns the alias for the field (the friendly displayed name of the field ),
* or an empty string if there is no alias.

View File

@ -71,6 +71,9 @@ class QgsFieldPrivate : public QSharedData
, alias( other.alias )
, defaultValueExpression( other.defaultValueExpression )
, constraints( other.constraints )
, constraintOrigins( other.constraintOrigins )
, expressionConstraint( other.expressionConstraint )
, expressionConstraintDescription( other.expressionConstraintDescription )
{
}
@ -81,7 +84,10 @@ class QgsFieldPrivate : public QSharedData
return (( name == other.name ) && ( type == other.type ) && ( subType == other.subType )
&& ( length == other.length ) && ( precision == other.precision )
&& ( alias == other.alias ) && ( defaultValueExpression == other.defaultValueExpression )
&& ( constraints == other.constraints ) );
&& ( constraints == other.constraints )
&& ( expressionConstraint == other.expressionConstraint )
&& ( expressionConstraintDescription == other.expressionConstraintDescription )
&& ( constraintOrigins == other.constraintOrigins ) );
}
//! Name
@ -114,6 +120,15 @@ class QgsFieldPrivate : public QSharedData
//! Constraints
QgsField::Constraints constraints;
//! Origin of field constraints
QHash< QgsField::Constraint, QgsField::ConstraintOrigin > constraintOrigins;
//! Expression constraint
QString expressionConstraint;
//! Expression constraint descriptive name
QString expressionConstraintDescription;
QgsEditorWidgetSetup editorWidgetSetup;
};

View File

@ -100,8 +100,11 @@ QVariant QgsVectorDataProvider::defaultValue( int fieldId ) const
QgsField::Constraints QgsVectorDataProvider::fieldConstraints( int fieldIndex ) const
{
Q_UNUSED( fieldIndex );
return 0;
QgsFields f = fields();
if ( fieldIndex < 0 || fieldIndex >= f.count() )
return 0;
return f.at( fieldIndex ).constraints();
}
bool QgsVectorDataProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )

View File

@ -286,7 +286,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
* field index.
* @note added in QGIS 3.0
*/
virtual QgsField::Constraints fieldConstraints( int fieldIndex ) const;
QgsField::Constraints fieldConstraints( int fieldIndex ) const;
/**
* Changes geometries of existing features

View File

@ -2940,7 +2940,12 @@ void QgsVectorLayer::updateFields()
continue;
// always keep provider constraints intact
mFields[ index ].setConstraints( mFields.at( index ).constraints() | constraintIt.value() );
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintNotNull ) && ( constraintIt.value() & QgsField::ConstraintNotNull ) )
mFields[ index ].setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginLayer );
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintUnique ) && ( constraintIt.value() & QgsField::ConstraintUnique ) )
mFields[ index ].setConstraint( QgsField::ConstraintUnique, QgsField::ConstraintOriginLayer );
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintExpression ) && ( constraintIt.value() & QgsField::ConstraintExpression ) )
mFields[ index ].setConstraint( QgsField::ConstraintExpression, QgsField::ConstraintOriginLayer );
}
if ( oldFields != mFields )

View File

@ -148,7 +148,7 @@ void QgsEditorWidgetWrapper::updateConstraint( const QgsFeature &ft )
else
mValidConstraint = true;
if ( layer()->fieldConstraints( mFieldIdx ) & QgsField::ConstraintNotNull )
if ( layer()->fields().at( mFieldIdx ).constraints() & QgsField::ConstraintNotNull )
{
descriptions << QStringLiteral( "NotNull" );
if ( !expression.isEmpty() )
@ -170,7 +170,7 @@ void QgsEditorWidgetWrapper::updateConstraint( const QgsFeature &ft )
toEmit = true;
}
if ( layer()->fieldConstraints( mFieldIdx ) & QgsField::ConstraintUnique )
if ( layer()->fields().at( mFieldIdx ).constraints() & QgsField::ConstraintUnique )
{
descriptions << QStringLiteral( "Unique" );
if ( !expression.isEmpty() )

View File

@ -674,7 +674,7 @@ void QgsAttributeForm::onAttributeChanged( const QVariant& value )
break;
}
if ( eww->layer()->fieldConstraints( eww->fieldIdx() ) & QgsField::ConstraintNotNull )
if ( eww->layer()->fields().at( eww->fieldIdx() ).constraints() & QgsField::ConstraintNotNull )
{
QLabel* buddy = mBuddyMap.value( eww->widget() );

View File

@ -1000,12 +1000,10 @@ bool QgsPostgresProvider::loadFields()
QgsField newField = QgsField( fieldName, fieldType, fieldTypeName, fieldSize, fieldPrec, fieldComment, fieldSubType );
QgsField::Constraints constraints = 0;
if ( notNullMap[tableoid][attnum] )
constraints |= QgsField::ConstraintNotNull;
newField.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
if ( uniqueMap[tableoid][attnum] )
constraints |= QgsField::ConstraintUnique;
newField.setConstraints( constraints );
newField.setConstraint( QgsField::ConstraintUnique, QgsField::ConstraintOriginProvider );
mAttributeFields.append( newField );
}
@ -1738,14 +1736,6 @@ QVariant QgsPostgresProvider::defaultValue( int fieldId ) const
return defVal;
}
QgsField::Constraints QgsPostgresProvider::fieldConstraints( int fieldIndex ) const
{
if ( fieldIndex < 0 || fieldIndex >= mAttributeFields.count() )
return 0;
return mAttributeFields.at( fieldIndex ).constraints();
}
QString QgsPostgresProvider::paramValue( const QString& fieldValue, const QString &defaultValue ) const
{
if ( fieldValue.isNull() )

View File

@ -161,7 +161,6 @@ class QgsPostgresProvider : public QgsVectorDataProvider
QgsAttributeList attributeIndexes() const override;
QgsAttributeList pkAttributeIndexes() const override { return mPrimaryKeyAttrs; }
QVariant defaultValue( int fieldId ) const override;
QgsField::Constraints fieldConstraints( int fieldIndex ) const override;
/** Adds a list of features
@return true in case of success and false in case of failure*/

View File

@ -842,16 +842,13 @@ void QgsSpatiaLiteProvider::fetchConstraints()
field = field.trimmed();
QString fieldName = field.left( field.indexOf( ' ' ) );
QString definition = field.mid( field.indexOf( ' ' ) + 1 );
QgsField::Constraints constraints = 0;
if ( definition.contains( "unique", Qt::CaseInsensitive ) || definition.contains( "primary key", Qt::CaseInsensitive ) )
constraints |= QgsField::ConstraintUnique;
if ( definition.contains( "not null", Qt::CaseInsensitive ) || definition.contains( "primary key", Qt::CaseInsensitive ) )
constraints |= QgsField::ConstraintNotNull;
int fieldIdx = mAttributeFields.lookupField( fieldName );
if ( fieldIdx >= 0 )
{
mAttributeFields[ fieldIdx ].setConstraints( constraints );
if ( definition.contains( "unique", Qt::CaseInsensitive ) || definition.contains( "primary key", Qt::CaseInsensitive ) )
mAttributeFields[ fieldIdx ].setConstraint( QgsField::ConstraintUnique, QgsField::ConstraintOriginProvider );
if ( definition.contains( "not null", Qt::CaseInsensitive ) || definition.contains( "primary key", Qt::CaseInsensitive ) )
mAttributeFields[ fieldIdx ].setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
}
}
}
@ -3666,14 +3663,6 @@ void QgsSpatiaLiteProvider::uniqueValues( int index, QList < QVariant > &uniqueV
return;
}
QgsField::Constraints QgsSpatiaLiteProvider::fieldConstraints( int fieldIndex ) const
{
if ( fieldIndex < 0 || fieldIndex >= mAttributeFields.count() )
return 0;
return mAttributeFields.at( fieldIndex ).constraints();
}
QString QgsSpatiaLiteProvider::geomParam() const
{
QString geometry;

View File

@ -130,7 +130,6 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
QVariant minimumValue( int index ) const override;
QVariant maximumValue( int index ) const override;
virtual void uniqueValues( int index, QList < QVariant > &uniqueValues, int limit = -1 ) const override;
QgsField::Constraints fieldConstraints( int fieldIndex ) const override;
bool isValid() const override;
virtual bool isSaveAndLoadStyleToDBSupported() const override { return true; }

View File

@ -84,7 +84,8 @@ void TestQgsField::create()
void TestQgsField::copy()
{
QgsField original( QStringLiteral( "original" ), QVariant::Double, QStringLiteral( "double" ), 5, 2, QStringLiteral( "comment" ) );
original.setConstraints( QgsField::ConstraintNotNull );
original.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
original.setConstraintExpression( QStringLiteral( "constraint expression" ), QStringLiteral( "description" ) );
QgsField copy( original );
QVERIFY( copy == original );
@ -96,7 +97,8 @@ void TestQgsField::copy()
void TestQgsField::assignment()
{
QgsField original( QStringLiteral( "original" ), QVariant::Double, QStringLiteral( "double" ), 5, 2, QStringLiteral( "comment" ) );
original.setConstraints( QgsField::ConstraintNotNull );
original.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
original.setConstraintExpression( QStringLiteral( "constraint expression" ), QStringLiteral( "description" ) );
QgsField copy;
copy = original;
QVERIFY( copy == original );
@ -125,8 +127,22 @@ void TestQgsField::gettersSetters()
QCOMPARE( field.alias(), QString( "alias" ) );
field.setDefaultValueExpression( QStringLiteral( "1+2" ) );
QCOMPARE( field.defaultValueExpression(), QString( "1+2" ) );
field.setConstraints( QgsField::ConstraintNotNull );
field.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
QCOMPARE( field.constraints(), QgsField::ConstraintNotNull );
QCOMPARE( field.constraintOrigin( QgsField::ConstraintNotNull ), QgsField::ConstraintOriginProvider );
QCOMPARE( field.constraintOrigin( QgsField::ConstraintUnique ), QgsField::ConstraintOriginNotSet );
field.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginNotSet );
QCOMPARE( field.constraints(), 0 );
field.setConstraint( QgsField::ConstraintUnique );
field.setConstraint( QgsField::ConstraintNotNull );
QCOMPARE( field.constraints(), QgsField::ConstraintUnique | QgsField::ConstraintNotNull );
field.removeConstraint( QgsField::ConstraintNotNull );
QCOMPARE( field.constraints(), QgsField::ConstraintUnique );
field.setConstraintExpression( QStringLiteral( "constraint expression" ), QStringLiteral( "description" ) );
QCOMPARE( field.constraintExpression(), QStringLiteral( "constraint expression" ) );
QCOMPARE( field.constraintDescription(), QStringLiteral( "description" ) );
QCOMPARE( field.constraints(), QgsField::ConstraintUnique | QgsField::ConstraintExpression ); //setting constraint expression should add constraint
}
void TestQgsField::isNumeric()
@ -161,7 +177,7 @@ void TestQgsField::equality()
field1.setPrecision( 2 );
field1.setTypeName( QStringLiteral( "typename1" ) ); //typename is NOT required for equality
field1.setComment( QStringLiteral( "comment1" ) ); //comment is NOT required for equality
field1.setConstraints( QgsField::ConstraintNotNull );
field1.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
QgsField field2;
field2.setName( QStringLiteral( "name" ) );
field2.setType( QVariant::Int );
@ -169,7 +185,7 @@ void TestQgsField::equality()
field2.setPrecision( 2 );
field2.setTypeName( QStringLiteral( "typename2" ) ); //typename is NOT required for equality
field2.setComment( QStringLiteral( "comment2" ) ); //comment is NOT required for equality
field2.setConstraints( QgsField::ConstraintNotNull );
field2.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
QVERIFY( field1 == field2 );
QVERIFY( !( field1 != field2 ) );
@ -198,16 +214,26 @@ void TestQgsField::equality()
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setDefaultValueExpression( QString() );
field2.setConstraints( QgsField::ConstraintUnique );
field2.removeConstraint( QgsField::ConstraintNotNull );
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setConstraints( QgsField::ConstraintNotNull );
field2.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginLayer );
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
field2.setConstraintExpression( QStringLiteral( "exp" ) );
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setConstraintExpression( QStringLiteral( "exp" ), QStringLiteral( "desc" ) );
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setConstraintExpression( QString(), QString() );
}
void TestQgsField::asVariant()
{
QgsField original( QStringLiteral( "original" ), QVariant::Double, QStringLiteral( "double" ), 5, 2, QStringLiteral( "comment" ) );
original.setConstraints( QgsField::ConstraintNotNull );
original.setConstraint( QgsField::ConstraintNotNull );
//convert to and from a QVariant
QVariant var = QVariant::fromValue( original );
@ -386,7 +412,9 @@ void TestQgsField::dataStream()
original.setComment( QStringLiteral( "comment1" ) );
original.setAlias( QStringLiteral( "alias" ) );
original.setDefaultValueExpression( QStringLiteral( "default" ) );
original.setConstraints( QgsField::ConstraintNotNull );
original.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
original.setConstraint( QgsField::ConstraintUnique, QgsField::ConstraintOriginLayer );
original.setConstraintExpression( QStringLiteral( "constraint expression" ), QStringLiteral( "description" ) );
QByteArray ba;
QDataStream ds( &ba, QIODevice::ReadWrite );

View File

@ -455,8 +455,10 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
# test that constraints have been saved to fields correctly
fields = vl.fields()
self.assertTrue(fields.at(0).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(0).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(1).constraints() & QgsField.ConstraintNotNull)
self.assertTrue(fields.at(2).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(2).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(3).constraints() & QgsField.ConstraintNotNull)
def testUniqueConstraint(self):
@ -476,8 +478,11 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
# test that constraints have been saved to fields correctly
fields = vl.fields()
self.assertTrue(fields.at(0).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(0).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
self.assertTrue(fields.at(1).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(1).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
self.assertTrue(fields.at(2).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(2).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(3).constraints() & QgsField.ConstraintUnique)
def testConstraintOverwrite(self):

View File

@ -388,7 +388,7 @@ class TestQgsSpatialiteProvider(unittest.TestCase, ProviderTestCase):
def testNotNullConstraint(self):
vl = QgsVectorLayer("dbname=%s table=test_constraints key='id'" % self.dbname, "test_constraints",
"spatialite")
"spatialite")
self.assertTrue(vl.isValid())
self.assertEqual(len(vl.fields()), 5)
@ -405,14 +405,17 @@ class TestQgsSpatialiteProvider(unittest.TestCase, ProviderTestCase):
# test that constraints have been saved to fields correctly
fields = vl.fields()
self.assertTrue(fields.at(0).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(0).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)
self.assertTrue(fields.at(1).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(1).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(2).constraints() & QgsField.ConstraintNotNull)
self.assertFalse(fields.at(3).constraints() & QgsField.ConstraintNotNull)
self.assertTrue(fields.at(4).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(4).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)
def testUniqueConstraint(self):
vl = QgsVectorLayer("dbname=%s table=test_constraints key='id'" % self.dbname, "test_constraints",
"spatialite")
"spatialite")
self.assertTrue(vl.isValid())
self.assertEqual(len(vl.fields()), 5)
@ -429,10 +432,13 @@ class TestQgsSpatialiteProvider(unittest.TestCase, ProviderTestCase):
# test that constraints have been saved to fields correctly
fields = vl.fields()
self.assertTrue(fields.at(0).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(0).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(1).constraints() & QgsField.ConstraintUnique)
self.assertTrue(fields.at(2).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(2).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
self.assertFalse(fields.at(3).constraints() & QgsField.ConstraintUnique)
self.assertTrue(fields.at(4).constraints() & QgsField.ConstraintUnique)
self.assertEqual(fields.at(4).constraintOrigin(QgsField.ConstraintUnique), QgsField.ConstraintOriginProvider)
# This test would fail. It would require turning on WAL
def XXXXXtestLocking(self):

View File

@ -1786,20 +1786,32 @@ class TestQgsVectorLayer(unittest.TestCase):
self.assertFalse(layer.fieldConstraints(1))
self.assertFalse(layer.fieldConstraints(2))
self.assertEqual(layer.fields().at(0).constraints(), QgsField.ConstraintNotNull)
self.assertEqual(layer.fields().at(0).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
layer.setFieldConstraints(1, QgsField.ConstraintNotNull | QgsField.ConstraintUnique)
self.assertEqual(layer.fieldConstraints(0), QgsField.ConstraintNotNull)
self.assertEqual(layer.fieldConstraints(1), QgsField.ConstraintNotNull | QgsField.ConstraintUnique)
self.assertFalse(layer.fieldConstraints(2))
self.assertEqual(layer.fields().at(0).constraints(), QgsField.ConstraintNotNull)
self.assertEqual(layer.fields().at(0).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
self.assertEqual(layer.fields().at(1).constraints(), QgsField.ConstraintNotNull | QgsField.ConstraintUnique)
self.assertEqual(layer.fields().at(1).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
self.assertEqual(layer.fields().at(1).constraintOrigin(QgsField.ConstraintUnique),
QgsField.ConstraintOriginLayer)
layer.setFieldConstraints(1, QgsField.Constraints())
self.assertEqual(layer.fieldConstraints(0), QgsField.ConstraintNotNull)
self.assertFalse(layer.fieldConstraints(1))
self.assertFalse(layer.fieldConstraints(2))
self.assertEqual(layer.fields().at(0).constraints(), QgsField.ConstraintNotNull)
self.assertEqual(layer.fields().at(0).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
self.assertFalse(layer.fields().at(1).constraints())
self.assertEqual(layer.fields().at(1).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginNotSet)
def testSaveRestoreConstraints(self):
""" test saving and restoring constraints from xml"""
@ -1828,7 +1840,13 @@ class TestQgsVectorLayer(unittest.TestCase):
self.assertEqual(layer3.fieldConstraints(0), QgsField.ConstraintNotNull)
self.assertEqual(layer3.fieldConstraints(1), QgsField.ConstraintNotNull | QgsField.ConstraintUnique)
self.assertEqual(layer3.fields().at(0).constraints(), QgsField.ConstraintNotNull)
self.assertEqual(layer.fields().at(0).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
self.assertEqual(layer3.fields().at(1).constraints(), QgsField.ConstraintNotNull | QgsField.ConstraintUnique)
self.assertEqual(layer.fields().at(1).constraintOrigin(QgsField.ConstraintNotNull),
QgsField.ConstraintOriginLayer)
self.assertEqual(layer.fields().at(1).constraintOrigin(QgsField.ConstraintUnique),
QgsField.ConstraintOriginLayer)
def testGetFeatureLimitWithEdits(self):
""" test getting features with a limit, when edits are present """