@@ -264,6 +264,87 @@ QVariant QgsVectorLayerUtils::createUniqueValue( const QgsVectorLayer *layer, in
264264 return QVariant ();
265265}
266266
267+ QVariant QgsVectorLayerUtils::createUniqueValueFromCache ( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed )
268+ {
269+ if ( !layer )
270+ return QVariant ();
271+
272+ QgsFields fields = layer->fields ();
273+
274+ if ( fieldIndex < 0 || fieldIndex >= fields.count () )
275+ return QVariant ();
276+
277+ QgsField field = fields.at ( fieldIndex );
278+
279+ if ( field.isNumeric () )
280+ {
281+ QVariant maxVal = existingValues.isEmpty () ? 0 : *std::max_element ( existingValues.begin (), existingValues.end () );
282+ QVariant newVar ( maxVal.toLongLong () + 1 );
283+ if ( field.convertCompatible ( newVar ) )
284+ return newVar;
285+ else
286+ return QVariant ();
287+ }
288+ else
289+ {
290+ switch ( field.type () )
291+ {
292+ case QVariant::String:
293+ {
294+ QString base;
295+ if ( seed.isValid () )
296+ base = seed.toString ();
297+
298+ if ( !base.isEmpty () )
299+ {
300+ // strip any existing _1, _2 from the seed
301+ QRegularExpression rx ( QStringLiteral ( " (.*)_\\ d+" ) );
302+ QRegularExpressionMatch match = rx.match ( base );
303+ if ( match.hasMatch () )
304+ {
305+ base = match.captured ( 1 );
306+ }
307+ }
308+ else
309+ {
310+ // no base seed - fetch first value from layer
311+ QgsFeatureRequest req;
312+ base = existingValues.isEmpty () ? QString () : existingValues.values ().first ().toString ();
313+ }
314+
315+ // try variants like base_1, base_2, etc until a new value found
316+ QStringList vals;
317+ for ( const auto &v : qgis::as_const ( existingValues ) )
318+ {
319+ if ( v.toString ().startsWith ( base ) )
320+ vals.push_back ( v.toString () );
321+ }
322+
323+ // might already be unique
324+ if ( !base.isEmpty () && !vals.contains ( base ) )
325+ return base;
326+
327+ for ( int i = 1 ; i < 10000 ; ++i )
328+ {
329+ QString testVal = base + ' _' + QString::number ( i );
330+ if ( !vals.contains ( testVal ) )
331+ return testVal;
332+ }
333+
334+ // failed
335+ return QVariant ();
336+ }
337+
338+ default :
339+ // todo other types - dates? times?
340+ break ;
341+ }
342+ }
343+
344+ return QVariant ();
345+
346+ }
347+
267348bool QgsVectorLayerUtils::validateAttribute ( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
268349 QgsFieldConstraints::ConstraintStrength strength, QgsFieldConstraints::ConstraintOrigin origin )
269350{
@@ -468,7 +549,7 @@ QgsFeatureList QgsVectorLayerUtils::createFeatures( const QgsVectorLayer *layer,
468549 if ( uniqueValueCaches[ idx ].contains ( v ) )
469550 {
470551 // unique constraint violated
471- QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValue ( layer, idx, v );
552+ QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache ( layer, idx, uniqueValueCaches[ idx ] , v );
472553 if ( uniqueValue.isValid () )
473554 v = uniqueValue;
474555 }
0 commit comments