mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Split handling of literal default values from provider side
default value SQL clauses QgsVectorDataProvider now has two methods: - defaultValueClause: returns SQL fragment which must be evaluated by the provider to obtain the default value, eg sequence values - defaultValue: returns the literal constant default value for a field
This commit is contained in:
parent
59b10d65b7
commit
1fea20de50
@ -226,9 +226,20 @@ class QgsVectorDataProvider : QgsDataProvider
|
||||
const QMap<qint64, QgsGeometry> &geometry_map );
|
||||
|
||||
/**
|
||||
* Returns the default value for field specified by @c fieldId
|
||||
* Returns any literal default values which are present at the provider for a specified
|
||||
* field index.
|
||||
* @see defaultValueClause()
|
||||
*/
|
||||
virtual QVariant defaultValue( int fieldId ) const;
|
||||
virtual QVariant defaultValue( int fieldIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns any default value clauses which are present at the provider for a specified
|
||||
* field index. These clauses are usually SQL fragments which must be evaluated by the
|
||||
* provider, eg sequence values.
|
||||
* @see defaultValue()
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
virtual QString defaultValueClause( int fieldIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns any constraints which are present at the provider for a specified
|
||||
|
@ -6988,7 +6988,7 @@ void QgisApp::mergeAttributesOfSelectedFeatures()
|
||||
QgsField fld( vl->fields().at( i ) );
|
||||
bool isDefaultValue = vl->fields().fieldOrigin( i ) == QgsFields::OriginProvider &&
|
||||
vl->dataProvider() &&
|
||||
vl->dataProvider()->defaultValue( vl->fields().fieldOriginIndex( i ) ) == val;
|
||||
vl->dataProvider()->defaultValueClause( vl->fields().fieldOriginIndex( i ) ) == val;
|
||||
|
||||
// convert to destination data type
|
||||
if ( !isDefaultValue && !fld.convertCompatible( val ) )
|
||||
@ -7167,7 +7167,7 @@ void QgisApp::mergeSelectedFeatures()
|
||||
QVariant val = attrs.at( i );
|
||||
bool isDefaultValue = vl->fields().fieldOrigin( i ) == QgsFields::OriginProvider &&
|
||||
vl->dataProvider() &&
|
||||
vl->dataProvider()->defaultValue( vl->fields().fieldOriginIndex( i ) ) == val;
|
||||
vl->dataProvider()->defaultValueClause( vl->fields().fieldOriginIndex( i ) ) == val;
|
||||
|
||||
// convert to destination data type
|
||||
if ( !isDefaultValue && !vl->fields().at( i ).convertCompatible( val ) )
|
||||
@ -7481,7 +7481,7 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
|
||||
}
|
||||
else
|
||||
{
|
||||
defVal = pasteVectorLayer->dataProvider()->defaultValue( dst );
|
||||
defVal = pasteVectorLayer->dataProvider()->defaultValueClause( dst );
|
||||
}
|
||||
|
||||
if ( defVal.isValid() && !defVal.isNull() )
|
||||
|
@ -176,7 +176,7 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
|
||||
}
|
||||
else
|
||||
{
|
||||
v = provider->defaultValue( idx );
|
||||
v = provider->defaultValueClause( idx );
|
||||
}
|
||||
|
||||
mFeature->setAttribute( idx, v );
|
||||
|
@ -489,7 +489,7 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
|
||||
|
||||
QString defVal;
|
||||
if ( fields.fieldOrigin( i ) == QgsFields::OriginProvider && vlayer->dataProvider() )
|
||||
defVal = vlayer->dataProvider()->defaultValue( fields.fieldOriginIndex( i ) ).toString();
|
||||
defVal = vlayer->dataProvider()->defaultValueClause( fields.fieldOriginIndex( i ) );
|
||||
|
||||
QString value = defVal == attrs.at( i ) ? defVal : fields.at( i ).displayString( attrs.at( i ) );
|
||||
QgsTreeWidgetItem *attrItem = new QgsTreeWidgetItem( QStringList() << QString::number( i ) << value );
|
||||
|
@ -540,7 +540,7 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
|
||||
if ( !mVectorLayer->defaultValueExpression( fieldIdx ).isEmpty() )
|
||||
results[fieldIdx] = mVectorLayer->defaultValue( fieldIdx, mFeatureList.at( 0 ), &context );
|
||||
else if ( mVectorLayer->dataProvider() )
|
||||
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValue( fieldIdx );
|
||||
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValueClause( fieldIdx );
|
||||
else
|
||||
results[fieldIdx] = QVariant();
|
||||
continue;
|
||||
@ -567,7 +567,7 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
|
||||
}
|
||||
else if ( mVectorLayer->dataProvider() )
|
||||
{
|
||||
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValue( fieldIdx );
|
||||
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValueClause( fieldIdx );
|
||||
}
|
||||
widgetIndex++;
|
||||
}
|
||||
|
@ -793,7 +793,7 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec
|
||||
if ( !remoteLayer->defaultValueExpression( k ).isEmpty() )
|
||||
newAttrs[k] = remoteLayer->defaultValue( k, f, &context );
|
||||
else if ( remoteFlds.fieldOrigin( k ) == QgsFields::OriginProvider )
|
||||
newAttrs[k] = remoteLayer->dataProvider()->defaultValue( remoteFlds.fieldOriginIndex( k ) );
|
||||
newAttrs[k] = remoteLayer->dataProvider()->defaultValueClause( remoteFlds.fieldOriginIndex( k ) );
|
||||
}
|
||||
|
||||
f.setAttributes( newAttrs );
|
||||
|
@ -98,6 +98,12 @@ QVariant QgsVectorDataProvider::defaultValue( int fieldId ) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString QgsVectorDataProvider::defaultValueClause( int fieldIndex ) const
|
||||
{
|
||||
Q_UNUSED( fieldIndex );
|
||||
return QString();
|
||||
}
|
||||
|
||||
QgsFieldConstraints::Constraints QgsVectorDataProvider::fieldConstraints( int fieldIndex ) const
|
||||
{
|
||||
QgsFields f = fields();
|
||||
|
@ -277,9 +277,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
||||
const QgsGeometryMap &geometry_map );
|
||||
|
||||
/**
|
||||
* Returns the default value for field specified by @c fieldId
|
||||
* Returns any literal default values which are present at the provider for a specified
|
||||
* field index.
|
||||
* @see defaultValueClause()
|
||||
*/
|
||||
virtual QVariant defaultValue( int fieldId ) const;
|
||||
virtual QVariant defaultValue( int fieldIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns any default value clauses which are present at the provider for a specified
|
||||
* field index. These clauses are usually SQL fragments which must be evaluated by the
|
||||
* provider, eg sequence values.
|
||||
* @see defaultValue()
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
virtual QString defaultValueClause( int fieldIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns any constraints which are present at the provider for a specified
|
||||
|
@ -381,7 +381,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
|
||||
QgsAttributes newAttributes = feat.attributes();
|
||||
Q_FOREACH ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
|
||||
{
|
||||
const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
|
||||
const QVariant defaultValue = L->dataProvider()->defaultValueClause( pkIdx );
|
||||
if ( !defaultValue.isNull() )
|
||||
{
|
||||
newAttributes[ pkIdx ] = defaultValue;
|
||||
|
@ -70,7 +70,7 @@ QString QgsEditorWidgetFactory::representValue( QgsVectorLayer* vl, int fieldIdx
|
||||
|
||||
QString defVal;
|
||||
if ( vl->fields().fieldOrigin( fieldIdx ) == QgsFields::OriginProvider && vl->dataProvider() )
|
||||
defVal = vl->dataProvider()->defaultValue( vl->fields().fieldOriginIndex( fieldIdx ) ).toString();
|
||||
defVal = vl->dataProvider()->defaultValueClause( vl->fields().fieldOriginIndex( fieldIdx ) );
|
||||
|
||||
return value == defVal ? defVal : vl->fields().at( fieldIdx ).displayString( value );
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ QgsField QgsEditorWidgetWrapper::field() const
|
||||
|
||||
QVariant QgsEditorWidgetWrapper::defaultValue() const
|
||||
{
|
||||
mDefaultValue = layer()->dataProvider()->defaultValue( mFieldIdx );
|
||||
mDefaultValue = layer()->dataProvider()->defaultValueClause( mFieldIdx );
|
||||
|
||||
return mDefaultValue;
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ void QgsMssqlProvider::loadFields()
|
||||
|
||||
if ( !query.value( 12 ).isNull() )
|
||||
{
|
||||
mDefaultValues.insert( i, query.value( 12 ) );
|
||||
mDefaultValues.insert( i, query.value( 12 ).toString() );
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@ -501,12 +501,9 @@ QString QgsMssqlProvider::quotedValue( const QVariant& value )
|
||||
}
|
||||
}
|
||||
|
||||
QVariant QgsMssqlProvider::defaultValue( int fieldId ) const
|
||||
QString QgsMssqlProvider::defaultValueClause( int fieldId ) const
|
||||
{
|
||||
if ( mDefaultValues.contains( fieldId ) )
|
||||
return mDefaultValues[fieldId];
|
||||
else
|
||||
return QVariant( QString::null );
|
||||
return mDefaultValues.value( fieldId, QString() );
|
||||
}
|
||||
|
||||
QString QgsMssqlProvider::storageType() const
|
||||
@ -815,7 +812,7 @@ bool QgsMssqlProvider::addFeatures( QgsFeatureList & flist )
|
||||
if ( fld.name().isEmpty() )
|
||||
continue; // invalid
|
||||
|
||||
if ( mDefaultValues.contains( i ) && mDefaultValues[i] == attrs.at( i ) )
|
||||
if ( mDefaultValues.contains( i ) && mDefaultValues.value( i ) == attrs.at( i ).toString() )
|
||||
continue; // skip fields having default values
|
||||
|
||||
if ( !first )
|
||||
@ -886,7 +883,7 @@ bool QgsMssqlProvider::addFeatures( QgsFeatureList & flist )
|
||||
if ( fld.name().isEmpty() )
|
||||
continue; // invalid
|
||||
|
||||
if ( mDefaultValues.contains( i ) && mDefaultValues[i] == attrs.at( i ) )
|
||||
if ( mDefaultValues.contains( i ) && mDefaultValues.value( i ) == attrs.at( i ).toString() )
|
||||
continue; // skip fields having default values
|
||||
|
||||
QVariant::Type type = fld.type();
|
||||
|
@ -186,7 +186,7 @@ class QgsMssqlProvider : public QgsVectorDataProvider
|
||||
//! Convert values to quoted values for database work *
|
||||
static QString quotedValue( const QVariant& value );
|
||||
|
||||
QVariant defaultValue( int fieldId ) const override;
|
||||
QString defaultValueClause( int fieldId ) const override;
|
||||
|
||||
//! Import a vector layer into the database
|
||||
static QgsVectorLayerImport::ImportError createEmptyLayer(
|
||||
@ -212,7 +212,7 @@ class QgsMssqlProvider : public QgsVectorDataProvider
|
||||
|
||||
//! Fields
|
||||
QgsFields mAttributeFields;
|
||||
QMap<int, QVariant> mDefaultValues;
|
||||
QMap<int, QString> mDefaultValues;
|
||||
|
||||
mutable QgsMssqlGeometryParser mParser;
|
||||
|
||||
|
@ -1716,15 +1716,27 @@ bool QgsPostgresProvider::isValid() const
|
||||
return mValid;
|
||||
}
|
||||
|
||||
QString QgsPostgresProvider::defaultValueClause( int fieldId ) const
|
||||
{
|
||||
QString defVal = mDefaultValues.value( fieldId, QString() );
|
||||
|
||||
if ( !providerProperty( EvaluateDefaultValues, false ).toBool() && !defVal.isEmpty() )
|
||||
{
|
||||
return defVal;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QVariant QgsPostgresProvider::defaultValue( int fieldId ) const
|
||||
{
|
||||
QVariant defVal = mDefaultValues.value( fieldId, QString::null );
|
||||
QString defVal = mDefaultValues.value( fieldId, QString() );
|
||||
|
||||
if ( providerProperty( EvaluateDefaultValues, false ).toBool() && !defVal.isNull() )
|
||||
if ( providerProperty( EvaluateDefaultValues, false ).toBool() && !defVal.isEmpty() )
|
||||
{
|
||||
QgsField fld = field( fieldId );
|
||||
|
||||
QgsPostgresResult res( connectionRO()->PQexec( QStringLiteral( "SELECT %1" ).arg( defVal.toString() ) ) );
|
||||
QgsPostgresResult res( connectionRO()->PQexec( QStringLiteral( "SELECT %1" ).arg( defVal ) ) );
|
||||
|
||||
if ( res.result() )
|
||||
return convertValue( fld.type(), fld.subType(), res.PQgetvalue( 0, 0 ) );
|
||||
@ -1735,7 +1747,7 @@ QVariant QgsPostgresProvider::defaultValue( int fieldId ) const
|
||||
}
|
||||
}
|
||||
|
||||
return defVal;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString QgsPostgresProvider::paramValue( const QString& fieldValue, const QString &defaultValue ) const
|
||||
@ -1891,7 +1903,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
|
||||
values += delim + QStringLiteral( "$%1" ).arg( defaultValues.size() + offset );
|
||||
delim = ',';
|
||||
fieldId << idx;
|
||||
defaultValues << defaultValue( idx ).toString();
|
||||
defaultValues << defaultValueClause( idx );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1928,7 +1940,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
|
||||
|
||||
insert += delim + quotedIdentifier( fieldname );
|
||||
|
||||
QString defVal = defaultValue( idx ).toString();
|
||||
QString defVal = defaultValueClause( idx );
|
||||
|
||||
if ( i == flist.size() )
|
||||
{
|
||||
|
@ -160,6 +160,7 @@ class QgsPostgresProvider : public QgsVectorDataProvider
|
||||
virtual bool isSaveAndLoadStyleToDBSupported() const override { return true; }
|
||||
QgsAttributeList attributeIndexes() const override;
|
||||
QgsAttributeList pkAttributeIndexes() const override { return mPrimaryKeyAttrs; }
|
||||
QString defaultValueClause( int fieldId ) const override;
|
||||
QVariant defaultValue( int fieldId ) const override;
|
||||
|
||||
/** Adds a list of features
|
||||
|
@ -28,6 +28,7 @@ from qgis.core import (
|
||||
QgsTransactionGroup,
|
||||
QgsField,
|
||||
QgsFieldConstraints,
|
||||
QgsDataProvider,
|
||||
NULL
|
||||
)
|
||||
from qgis.gui import QgsEditorWidgetRegistry
|
||||
@ -84,9 +85,17 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
|
||||
|
||||
# HERE GO THE PROVIDER SPECIFIC TESTS
|
||||
def testDefaultValue(self):
|
||||
self.assertEqual(self.provider.defaultValue(0), 'nextval(\'qgis_test."someData_pk_seq"\'::regclass)')
|
||||
self.provider.setProviderProperty(QgsDataProvider.EvaluateDefaultValues, True)
|
||||
self.assertTrue(isinstance(self.provider.defaultValue(0), int))
|
||||
self.assertEqual(self.provider.defaultValue(1), NULL)
|
||||
self.assertEqual(self.provider.defaultValue(2), '\'qgis\'::text')
|
||||
self.assertEqual(self.provider.defaultValue(2), 'qgis')
|
||||
self.provider.setProviderProperty(QgsDataProvider.EvaluateDefaultValues, False)
|
||||
|
||||
def testDefaultValueClause(self):
|
||||
self.provider.setProviderProperty(QgsDataProvider.EvaluateDefaultValues, False)
|
||||
self.assertEqual(self.provider.defaultValueClause(0), 'nextval(\'qgis_test."someData_pk_seq"\'::regclass)')
|
||||
self.assertFalse(self.provider.defaultValueClause(1))
|
||||
self.assertEqual(self.provider.defaultValueClause(2), '\'qgis\'::text')
|
||||
|
||||
def testDateTimeTypes(self):
|
||||
vl = QgsVectorLayer('%s table="qgis_test"."date_times" sql=' % (self.dbconn), "testdatetimes", "postgres")
|
||||
@ -248,7 +257,7 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
|
||||
vl = QgsVectorLayer('{} table="qgis_test"."{}" key="obj_id" sql='.format(self.dbconn, 'oid_serial_table'), "oid_serial", "postgres")
|
||||
self.assertTrue(vl.isValid())
|
||||
f = QgsFeature(vl.fields())
|
||||
f['obj_id'] = vl.dataProvider().defaultValue(0)
|
||||
f['obj_id'] = vl.dataProvider().defaultValueClause(0)
|
||||
f['name'] = 'Test'
|
||||
r, f = vl.dataProvider().addFeatures([f])
|
||||
self.assertTrue(r)
|
||||
@ -553,17 +562,17 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
|
||||
oflds = olyr.fields()
|
||||
if key is None:
|
||||
# if the pkey was not given, it will create a pkey
|
||||
self.assertEquals(oflds.size(), flds.size() + 1)
|
||||
self.assertEquals(oflds[0].name(), kfnames[0])
|
||||
self.assertEqual(oflds.size(), flds.size() + 1)
|
||||
self.assertEqual(oflds[0].name(), kfnames[0])
|
||||
for i in range(flds.size()):
|
||||
self.assertEqual(oflds[i + 1].name(), flds[i].name())
|
||||
else:
|
||||
# pkey was given, no extra field generated
|
||||
self.assertEquals(oflds.size(), flds.size())
|
||||
self.assertEqual(oflds.size(), flds.size())
|
||||
for i in range(oflds.size()):
|
||||
self.assertEqual(oflds[i].name(), flds[i].name())
|
||||
pks = olyr.pkAttributeList()
|
||||
self.assertEquals(len(pks), len(kfnames))
|
||||
self.assertEqual(len(pks), len(kfnames))
|
||||
for i in range(0, len(kfnames)):
|
||||
self.assertEqual(oflds[pks[i]].name(), kfnames[i])
|
||||
|
||||
|
@ -153,7 +153,7 @@ class TestQgsRelationEditWidget(unittest.TestCase):
|
||||
wrapper = self.createWrapper(self.vl_a, '"name"=\'Douglas Adams\'') # NOQA
|
||||
|
||||
f = QgsFeature(self.vl_b.fields())
|
||||
f.setAttributes([self.vl_b.dataProvider().defaultValue(0), 'The Hitchhiker\'s Guide to the Galaxy'])
|
||||
f.setAttributes([self.vl_b.dataProvider().defaultValueClause(0), 'The Hitchhiker\'s Guide to the Galaxy'])
|
||||
self.vl_b.addFeature(f)
|
||||
|
||||
def choose_linked_feature():
|
||||
@ -318,7 +318,7 @@ class VlTools(QgsVectorLayerTools):
|
||||
if v:
|
||||
values.append(v)
|
||||
else:
|
||||
values.append(layer.dataProvider().defaultValue(i))
|
||||
values.append(layer.dataProvider().defaultValueClause(i))
|
||||
f = QgsFeature(layer.fields())
|
||||
f.setAttributes(self.values)
|
||||
f.setGeometry(defaultGeometry)
|
||||
|
Loading…
x
Reference in New Issue
Block a user