QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsvectordataprovider.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectordataprovider.cpp - DataProvider Interface for vector layers
3  --------------------------------------
4  Date : 26-Oct-2004
5  Copyright : (C) 2004 by Marco Hugentobler
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QTextCodec>
17 
18 #include <cfloat>
19 #include <climits>
20 #include <limits>
21 
22 #include "qgsvectordataprovider.h"
23 #include "qgscircularstring.h"
24 #include "qgscompoundcurve.h"
25 #include "qgsfeature.h"
26 #include "qgsfeatureiterator.h"
27 #include "qgsfeaturerequest.h"
28 #include "qgsfeedback.h"
29 #include "qgsfields.h"
30 #include "qgsgeometry.h"
31 #include "qgsgeometrycollection.h"
32 #include "qgsgeometryfactory.h"
33 #include "qgslogger.h"
34 #include "qgsmessagelog.h"
35 #include "qgssettings.h"
36 #include "qgsogrproxytextcodec.h"
37 #include <mutex>
38 
40  QgsDataProvider::ReadFlags flags )
41  : QgsDataProvider( uri, options, flags )
42  , mTemporalCapabilities( std::make_unique< QgsVectorDataProviderTemporalCapabilities >() )
43 {
44 }
45 
47 {
48  return QStringLiteral( "Generic vector file" );
49 }
50 
52 {
53  QgsFeature f;
54  QgsFeatureRequest request;
55  request.setNoAttributes();
57  request.setLimit( 1 );
58  if ( getFeatures( request ).nextFeature( f ) )
59  return false;
60  else
61  return true;
62 }
63 
65 {
66  if ( empty() )
67  return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
68  else
69  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
70 }
71 
73 {
74  return crs();
75 }
76 
78 {
79  return extent();
80 }
81 
83 {
84  return QString();
85 }
86 
88 {
89  Q_UNUSED( flist )
90  Q_UNUSED( flags )
91  return false;
92 }
93 
95 {
96  return mErrors.isEmpty() ? QString() : mErrors.last();
97 }
98 
100 {
101  Q_UNUSED( ids )
102  return false;
103 }
104 
106 {
107  if ( !( capabilities() & DeleteFeatures ) )
108  return false;
109 
110  QgsFeatureIds toDelete;
111  QgsFeatureIterator it = getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setNoAttributes() );
112  QgsFeature f;
113  while ( it.nextFeature( f ) )
114  toDelete << f.id();
115 
116  return deleteFeatures( toDelete );
117 }
118 
119 bool QgsVectorDataProvider::addAttributes( const QList<QgsField> &attributes )
120 {
121  Q_UNUSED( attributes )
122  return false;
123 }
124 
126 {
127  Q_UNUSED( attributes )
128  return false;
129 }
130 
132 {
133  Q_UNUSED( renamedAttributes )
134  return false;
135 }
136 
138 {
139  Q_UNUSED( attr_map )
140  return false;
141 }
142 
143 QVariant QgsVectorDataProvider::defaultValue( int fieldId ) const
144 {
145  Q_UNUSED( fieldId )
146  return QVariant();
147 }
148 
149 QString QgsVectorDataProvider::defaultValueClause( int fieldIndex ) const
150 {
151  Q_UNUSED( fieldIndex )
152  return QString();
153 }
154 
155 QgsFieldConstraints::Constraints QgsVectorDataProvider::fieldConstraints( int fieldIndex ) const
156 {
157  const QgsFields f = fields();
158  if ( fieldIndex < 0 || fieldIndex >= f.count() )
159  return QgsFieldConstraints::Constraints();
160 
161  return f.at( fieldIndex ).constraints().constraints();
162 }
163 
165 {
166  return false;
167 }
168 
170 {
171  Q_UNUSED( geometry_map )
172  return false;
173 }
174 
176  const QgsGeometryMap &geometry_map )
177 {
179  return false;
180 
181  bool result = true;
182  result = result && changeAttributeValues( attr_map );
183  result = result && changeGeometryValues( geometry_map );
184  return result;
185 }
186 
188 {
189  return false;
190 }
191 
193 {
194  Q_UNUSED( field )
195  return true;
196 }
197 
198 QgsVectorDataProvider::Capabilities QgsVectorDataProvider::capabilities() const
199 {
201 }
202 
203 void QgsVectorDataProvider::setEncoding( const QString &e )
204 {
205  mEncoding = QTextCodec::codecForName( e.toLocal8Bit().constData() );
206  if ( !mEncoding && e != QLatin1String( "System" ) )
207  {
208  if ( !e.isEmpty() )
209  {
210  // can we use the OGR proxy codec?
211  if ( QgsOgrProxyTextCodec::supportedCodecs().contains( e, Qt::CaseInsensitive ) )
212  {
213  //from the Qt docs (https://doc.qt.io/qt-5/qtextcodec.html#QTextCodec-1)
214  // "The QTextCodec should always be constructed on the heap (i.e. with new).
215  // Qt takes ownership and will delete it when the application terminates."
216  mEncoding = new QgsOgrProxyTextCodec( e.toLocal8Bit() );
217  }
218  else
219  {
220  QgsMessageLog::logMessage( tr( "Codec %1 not found. Falling back to system locale" ).arg( e ) );
221  mEncoding = QTextCodec::codecForName( "System" );
222  }
223  }
224  }
225 
226  if ( !mEncoding )
227  mEncoding = QTextCodec::codecForLocale();
228 
229  Q_ASSERT( mEncoding );
230 }
231 
233 {
234  if ( mEncoding )
235  {
236  return mEncoding->name();
237  }
238 
239  return QString();
240 }
241 
243 {
244  QStringList abilitiesList;
245 
246  const int abilities = capabilities();
247 
248  if ( abilities & QgsVectorDataProvider::AddFeatures )
249  {
250  abilitiesList += tr( "Add Features" );
251  }
252 
253  if ( abilities & QgsVectorDataProvider::DeleteFeatures )
254  {
255  abilitiesList += tr( "Delete Features" );
256  }
257 
259  {
260  abilitiesList += tr( "Change Attribute Values" );
261  }
262 
263  if ( abilities & QgsVectorDataProvider::AddAttributes )
264  {
265  abilitiesList += tr( "Add Attributes" );
266  }
267 
268  if ( abilities & QgsVectorDataProvider::DeleteAttributes )
269  {
270  abilitiesList += tr( "Delete Attributes" );
271  }
272 
273  if ( abilities & QgsVectorDataProvider::RenameAttributes )
274  {
275  abilitiesList += tr( "Rename Attributes" );
276  }
277 
279  {
280  // TODO: Tighten up this test. See QgsOgrProvider for details.
281  abilitiesList += tr( "Create Spatial Index" );
282  }
283 
285  {
286  abilitiesList += tr( "Create Attribute Indexes" );
287  }
288 
289  if ( abilities & QgsVectorDataProvider::SelectAtId )
290  {
291  abilitiesList += tr( "Fast Access to Features at ID" );
292  }
293 
294  if ( abilities & QgsVectorDataProvider::ChangeGeometries )
295  {
296  abilitiesList += tr( "Change Geometries" );
297  }
298 
300  {
301  abilitiesList += tr( "Presimplify Geometries" );
302  }
303 
305  {
306  abilitiesList += tr( "Presimplify Geometries with Validity Check" );
307  }
308 
309  if ( abilities & QgsVectorDataProvider::ChangeFeatures )
310  {
311  abilitiesList += tr( "Simultaneous Geometry and Attribute Updates" );
312  }
313 
315  {
316  abilitiesList += tr( "Transactions" );
317  }
318 
320  {
321  abilitiesList += tr( "Curved Geometries" );
322  }
323 
324  if ( abilities & QgsVectorDataProvider::FeatureSymbology )
325  {
326  abilitiesList += tr( "Feature Symbology" );
327  }
328 
329  return abilitiesList.join( QLatin1String( ", " ) );
330 }
331 
332 
333 int QgsVectorDataProvider::fieldNameIndex( const QString &fieldName ) const
334 {
335  return fields().lookupField( fieldName );
336 }
337 
338 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
339 {
340  QMap<QString, int> resultMap;
341 
342  const QgsFields fieldsCopy = fields();
343  for ( int i = 0; i < fieldsCopy.count(); ++i )
344  {
345  resultMap.insert( fieldsCopy.at( i ).name(), i );
346  }
347 
348  return resultMap;
349 }
350 
352 {
353  return fields().allAttributesList();
354 }
355 
357 {
358  return QgsAttributeList();
359 }
360 
361 QList<QgsVectorDataProvider::NativeType> QgsVectorDataProvider::nativeTypes() const
362 {
363  return mNativeTypes;
364 }
365 
367 {
368  return QgsAttrPalIndexNameHash();
369 }
370 
372 {
373  QgsDebugMsgLevel( QStringLiteral( "field name = %1 type = %2 length = %3 precision = %4" )
374  .arg( field.name(),
375  QVariant::typeToName( field.type() ) )
376  .arg( field.length() )
377  .arg( field.precision() ), 2 );
378 
379  for ( const NativeType &nativeType : mNativeTypes )
380  {
381  QgsDebugMsgLevel( QStringLiteral( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
382  .arg( QVariant::typeToName( nativeType.mType ) )
383  .arg( nativeType.mMinLen )
384  .arg( nativeType.mMaxLen )
385  .arg( nativeType.mMinPrec )
386  .arg( nativeType.mMaxPrec ), 2 );
387 
388  if ( field.type() != nativeType.mType )
389  continue;
390 
391  if ( field.length() > 0 )
392  {
393  // source length limited
394  if ( ( nativeType.mMinLen > 0 && field.length() < nativeType.mMinLen ) ||
395  ( nativeType.mMaxLen > 0 && field.length() > nativeType.mMaxLen ) )
396  {
397  // source length exceeds destination limits
398  continue;
399  }
400  }
401 
402  if ( field.precision() > 0 )
403  {
404  // source precision limited
405  if ( ( nativeType.mMinPrec > 0 && field.precision() < nativeType.mMinPrec ) ||
406  ( nativeType.mMaxPrec > 0 && field.precision() > nativeType.mMaxPrec ) )
407  {
408  // source precision exceeds destination limits
409  continue;
410  }
411  }
412 
413  QgsDebugMsgLevel( QStringLiteral( "native type matches" ), 3 );
414  return true;
415  }
416 
417  QgsDebugMsg( QStringLiteral( "no sufficient native type found" ) );
418  return false;
419 }
420 
421 QVariant QgsVectorDataProvider::minimumValue( int index ) const
422 {
423  if ( index < 0 || index >= fields().count() )
424  {
425  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
426  return QVariant();
427  }
428 
429  fillMinMaxCache();
430 
431  if ( !mCacheMinValues.contains( index ) )
432  return QVariant();
433 
434  return mCacheMinValues[index];
435 }
436 
437 QVariant QgsVectorDataProvider::maximumValue( int index ) const
438 {
439  if ( index < 0 || index >= fields().count() )
440  {
441  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
442  return QVariant();
443  }
444 
445  fillMinMaxCache();
446 
447  if ( !mCacheMaxValues.contains( index ) )
448  return QVariant();
449 
450  return mCacheMaxValues[index];
451 }
452 
453 
454 QStringList QgsVectorDataProvider::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
455 {
456  QStringList results;
457 
458  // Safety belt
459  if ( index < 0 || index >= fields().count() )
460  return results;
461 
462  QgsFeature f;
463  QgsAttributeList keys;
464  keys.append( index );
465 
466  QgsFeatureRequest request;
467  request.setSubsetOfAttributes( keys );
469  const QString fieldName = fields().at( index ).name();
470  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
471  QgsFeatureIterator fi = getFeatures( request );
472 
473  QSet<QString> set;
474 
475  while ( fi.nextFeature( f ) )
476  {
477  const QString value = f.attribute( index ).toString();
478  if ( !set.contains( value ) )
479  {
480  results.append( value );
481  set.insert( value );
482  }
483 
484  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
485  break;
486  }
487  return results;
488 }
489 
491  const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool &ok, QgsFeatureIds *fids ) const
492 {
493  //base implementation does nothing
494  Q_UNUSED( aggregate )
495  Q_UNUSED( index )
496  Q_UNUSED( parameters )
497  Q_UNUSED( context )
498  Q_UNUSED( fids )
499 
500  ok = false;
501  return QVariant();
502 }
503 
505 {
506  mCacheMinMaxDirty = true;
507  mCacheMinValues.clear();
508  mCacheMaxValues.clear();
509 }
510 
512 {
513  if ( !mCacheMinMaxDirty )
514  return;
515 
516  const QgsFields flds = fields();
517  for ( int i = 0; i < flds.count(); ++i )
518  {
519  if ( flds.at( i ).type() == QVariant::Int )
520  {
521  mCacheMinValues[i] = QVariant( std::numeric_limits<int>::max() );
522  mCacheMaxValues[i] = QVariant( std::numeric_limits<int>::lowest() );
523  }
524  else if ( flds.at( i ).type() == QVariant::LongLong )
525  {
526  mCacheMinValues[i] = QVariant( std::numeric_limits<qlonglong>::max() );
527  mCacheMaxValues[i] = QVariant( std::numeric_limits<qlonglong>::lowest() );
528  }
529  else if ( flds.at( i ).type() == QVariant::Double )
530  {
531  mCacheMinValues[i] = QVariant( std::numeric_limits<double>::max() );
532  mCacheMaxValues[i] = QVariant( std::numeric_limits<double>::lowest() );
533 
534  }
535  else
536  {
537  mCacheMinValues[i] = QVariant();
538  mCacheMaxValues[i] = QVariant();
539  }
540  }
541 
542  QgsFeature f;
543  const QgsAttributeList keys = mCacheMinValues.keys();
544  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys )
545  .setFlags( QgsFeatureRequest::NoGeometry ) );
546 
547  while ( fi.nextFeature( f ) )
548  {
549  const QgsAttributes attrs = f.attributes();
550  for ( const int attributeIndex : keys )
551  {
552  const QVariant &varValue = attrs.at( attributeIndex );
553 
554  if ( varValue.isNull() )
555  continue;
556 
557  switch ( flds.at( attributeIndex ).type() )
558  {
559  case QVariant::Int:
560  {
561  const int value = varValue.toInt();
562  if ( value < mCacheMinValues[ attributeIndex ].toInt() )
563  mCacheMinValues[ attributeIndex ] = value;
564  if ( value > mCacheMaxValues[ attributeIndex ].toInt() )
565  mCacheMaxValues[ attributeIndex ] = value;
566  break;
567  }
568  case QVariant::LongLong:
569  {
570  const qlonglong value = varValue.toLongLong();
571  if ( value < mCacheMinValues[ attributeIndex ].toLongLong() )
572  mCacheMinValues[ attributeIndex ] = value;
573  if ( value > mCacheMaxValues[ attributeIndex ].toLongLong() )
574  mCacheMaxValues[ attributeIndex ] = value;
575  break;
576  }
577  case QVariant::Double:
578  {
579  const double value = varValue.toDouble();
580  if ( value < mCacheMinValues[ attributeIndex ].toDouble() )
581  mCacheMinValues[attributeIndex ] = value;
582  if ( value > mCacheMaxValues[ attributeIndex ].toDouble() )
583  mCacheMaxValues[ attributeIndex ] = value;
584  break;
585  }
586  case QVariant::DateTime:
587  {
588  const QDateTime value = varValue.toDateTime();
589  if ( value < mCacheMinValues[ attributeIndex ].toDateTime() || !mCacheMinValues[ attributeIndex ].isValid() )
590  mCacheMinValues[attributeIndex ] = value;
591  if ( value > mCacheMaxValues[ attributeIndex ].toDateTime() || !mCacheMaxValues[ attributeIndex ].isValid() )
592  mCacheMaxValues[ attributeIndex ] = value;
593  break;
594  }
595  case QVariant::Date:
596  {
597  const QDate value = varValue.toDate();
598  if ( value < mCacheMinValues[ attributeIndex ].toDate() || !mCacheMinValues[ attributeIndex ].isValid() )
599  mCacheMinValues[attributeIndex ] = value;
600  if ( value > mCacheMaxValues[ attributeIndex ].toDate() || !mCacheMaxValues[ attributeIndex ].isValid() )
601  mCacheMaxValues[ attributeIndex ] = value;
602  break;
603  }
604  case QVariant::Time:
605  {
606  const QTime value = varValue.toTime();
607  if ( value < mCacheMinValues[ attributeIndex ].toTime() || !mCacheMinValues[ attributeIndex ].isValid() )
608  mCacheMinValues[attributeIndex ] = value;
609  if ( value > mCacheMaxValues[ attributeIndex ].toTime() || !mCacheMaxValues[ attributeIndex ].isValid() )
610  mCacheMaxValues[ attributeIndex ] = value;
611  break;
612  }
613  default:
614  {
615  const QString value = varValue.toString();
616  if ( mCacheMinValues[ attributeIndex ].isNull() || value < mCacheMinValues[attributeIndex ].toString() )
617  {
618  mCacheMinValues[attributeIndex] = value;
619  }
620  if ( mCacheMaxValues[attributeIndex].isNull() || value > mCacheMaxValues[attributeIndex].toString() )
621  {
622  mCacheMaxValues[attributeIndex] = value;
623  }
624  break;
625  }
626  }
627  }
628  }
629 
630  mCacheMinMaxDirty = false;
631 }
632 
633 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, const QString &value )
634 {
635  QVariant v( value );
636 
637  if ( !v.convert( type ) || value.isNull() )
638  v = QVariant( type );
639 
640  return v;
641 }
642 
644 {
645  return nullptr;
646 }
647 
648 static bool _compareEncodings( const QString &s1, const QString &s2 )
649 {
650  return s1.toLower() < s2.toLower();
651 }
652 
654 {
655  static std::once_flag initialized;
656  std::call_once( initialized, [ = ]
657  {
658  const auto codecs { QTextCodec::availableCodecs() };
659  for ( const QByteArray &codec : codecs )
660  {
661  sEncodings << codec;
662  }
663 #if 0
664  smEncodings << "BIG5";
665  smEncodings << "BIG5-HKSCS";
666  smEncodings << "EUCJP";
667  smEncodings << "EUCKR";
668  smEncodings << "GB2312";
669  smEncodings << "GBK";
670  smEncodings << "GB18030";
671  smEncodings << "JIS7";
672  smEncodings << "SHIFT-JIS";
673  smEncodings << "TSCII";
674  smEncodings << "UTF-8";
675  smEncodings << "UTF-16";
676  smEncodings << "KOI8-R";
677  smEncodings << "KOI8-U";
678  smEncodings << "ISO8859-1";
679  smEncodings << "ISO8859-2";
680  smEncodings << "ISO8859-3";
681  smEncodings << "ISO8859-4";
682  smEncodings << "ISO8859-5";
683  smEncodings << "ISO8859-6";
684  smEncodings << "ISO8859-7";
685  smEncodings << "ISO8859-8";
686  smEncodings << "ISO8859-8-I";
687  smEncodings << "ISO8859-9";
688  smEncodings << "ISO8859-10";
689  smEncodings << "ISO8859-11";
690  smEncodings << "ISO8859-12";
691  smEncodings << "ISO8859-13";
692  smEncodings << "ISO8859-14";
693  smEncodings << "ISO8859-15";
694  smEncodings << "IBM 850";
695  smEncodings << "IBM 866";
696  smEncodings << "CP874";
697  smEncodings << "CP1250";
698  smEncodings << "CP1251";
699  smEncodings << "CP1252";
700  smEncodings << "CP1253";
701  smEncodings << "CP1254";
702  smEncodings << "CP1255";
703  smEncodings << "CP1256";
704  smEncodings << "CP1257";
705  smEncodings << "CP1258";
706  smEncodings << "Apple Roman";
707  smEncodings << "TIS-620";
708  smEncodings << "System";
709 #endif
710 
711  // Do case-insensitive sorting of encodings
712  std::sort( sEncodings.begin(), sEncodings.end(), _compareEncodings );
713 
714  } );
715 
716  return sEncodings;
717 }
718 
720 {
721  mErrors.clear();
722 }
723 
725 {
726  return !mErrors.isEmpty();
727 }
728 
729 QStringList QgsVectorDataProvider::errors() const
730 {
731  return mErrors;
732 }
733 
735 {
736  return false;
737 }
738 
740 {
741  return false;
742 }
743 
745 {
746  return nullptr;
747 }
748 
750 {
751  return nullptr;
752 }
753 
754 void QgsVectorDataProvider::pushError( const QString &msg ) const
755 {
756  QgsDebugMsg( msg );
757  mErrors << msg;
758  emit raiseError( msg );
759 }
760 
761 QSet<QgsMapLayerDependency> QgsVectorDataProvider::dependencies() const
762 {
763  return QSet<QgsMapLayerDependency>();
764 }
765 
767 {
768  if ( geom.isNull() )
769  {
770  return QgsGeometry();
771  }
772 
773  const QgsAbstractGeometry *geometry = geom.constGet();
774  if ( !geometry )
775  {
776  return QgsGeometry();
777  }
778 
779  const QgsWkbTypes::Type providerGeomType = wkbType();
780 
781  //geom is already in the provider geometry type
782  if ( geometry->wkbType() == providerGeomType )
783  {
784  return QgsGeometry();
785  }
786 
787  std::unique_ptr< QgsAbstractGeometry > outputGeom;
788 
789  //convert compoundcurve to circularstring (possible if compoundcurve consists of one circular string)
790  if ( QgsWkbTypes::flatType( providerGeomType ) == QgsWkbTypes::CircularString )
791  {
792  QgsCompoundCurve *compoundCurve = qgsgeometry_cast<QgsCompoundCurve *>( geometry );
793  if ( compoundCurve )
794  {
795  if ( compoundCurve->nCurves() == 1 )
796  {
797  const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( compoundCurve->curveAt( 0 ) );
798  if ( circularString )
799  {
800  outputGeom.reset( circularString->clone() );
801  }
802  }
803  }
804  }
805 
806  //convert to curved type if necessary
807  if ( !QgsWkbTypes::isCurvedType( geometry->wkbType() ) && QgsWkbTypes::isCurvedType( providerGeomType ) )
808  {
809  QgsAbstractGeometry *curveGeom = outputGeom ? outputGeom->toCurveType() : geometry->toCurveType();
810  if ( curveGeom )
811  {
812  outputGeom.reset( curveGeom );
813  }
814  }
815 
816  //convert to linear type from curved type
817  if ( QgsWkbTypes::isCurvedType( geometry->wkbType() ) && !QgsWkbTypes::isCurvedType( providerGeomType ) )
818  {
819  QgsAbstractGeometry *segmentizedGeom = outputGeom ? outputGeom->segmentize() : geometry->segmentize();
820  if ( segmentizedGeom )
821  {
822  outputGeom.reset( segmentizedGeom );
823  }
824  }
825 
826  //convert to multitype if necessary
827  if ( QgsWkbTypes::isMultiType( providerGeomType ) && !QgsWkbTypes::isMultiType( geometry->wkbType() ) )
828  {
829  std::unique_ptr< QgsAbstractGeometry > collGeom( QgsGeometryFactory::geomFromWkbType( providerGeomType ) );
830  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( collGeom.get() );
831  if ( geomCollection )
832  {
833  if ( geomCollection->addGeometry( outputGeom ? outputGeom->clone() : geometry->clone() ) )
834  {
835  outputGeom.reset( collGeom.release() );
836  }
837  }
838  }
839 
840  //convert to single type if there's a single part of compatible type
841  if ( !QgsWkbTypes::isMultiType( providerGeomType ) && QgsWkbTypes::isMultiType( geometry->wkbType() ) )
842  {
843  const QgsGeometryCollection *collection = qgsgeometry_cast<const QgsGeometryCollection *>( geometry );
844  if ( collection )
845  {
846  if ( collection->numGeometries() == 1 )
847  {
848  const QgsAbstractGeometry *firstGeom = collection->geometryN( 0 );
849  if ( firstGeom && firstGeom->wkbType() == providerGeomType )
850  {
851  outputGeom.reset( firstGeom->clone() );
852  }
853  }
854  }
855  }
856 
857  //set z/m types
858  if ( QgsWkbTypes::hasZ( providerGeomType ) )
859  {
860  if ( !outputGeom )
861  {
862  outputGeom.reset( geometry->clone() );
863  }
864  outputGeom->addZValue();
865  }
866 
867  if ( QgsWkbTypes::hasM( providerGeomType ) )
868  {
869  if ( !outputGeom )
870  {
871  outputGeom.reset( geometry->clone() );
872  }
873  outputGeom->addMValue();
874  }
875 
876  if ( outputGeom )
877  {
878  return QgsGeometry( outputGeom.release() );
879  }
880 
881  return QgsGeometry();
882 }
883 
884 void QgsVectorDataProvider::setNativeTypes( const QList<NativeType> &nativeTypes )
885 {
886  mNativeTypes = nativeTypes;
887 }
888 
890 {
891  return mEncoding;
892 }
893 
895 {
896  return false;
897 }
898 
899 QStringList QgsVectorDataProvider::sEncodings;
900 
901 QList<QgsRelation> QgsVectorDataProvider::discoverRelations( const QgsVectorLayer *, const QList<QgsVectorLayer *> & ) const
902 {
903  return QList<QgsRelation>();
904 }
905 
907 {
908 
909 }
910 
912 {
913  return mTemporalCapabilities.get();
914 }
915 
917 {
918  return mTemporalCapabilities.get();
919 }
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
virtual QgsAbstractGeometry * toCurveType() const =0
Returns the geometry converted to the more generic curve type.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
Aggregate
Available aggregates to calculate.
A vector of attributes.
Definition: qgsattributes.h:58
Circular string geometry type.
QgsCircularString * clone() const override
Clones the geometry by performing a deep copy.
Compound curve geometry type.
const QgsCurve * curveAt(int i) const SIP_HOLDGIL
Returns the curve at the specified index.
int nCurves() const SIP_HOLDGIL
Returns the number of curves in the geometry.
This class represents a coordinate reference system (CRS).
Abstract base class for spatial data provider implementations.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsRectangle extent() const =0
Returns the extent of the layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
FeatureAvailability
Possible return value for hasFeatures() to determine if a source is empty.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:320
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Constraint
Constraints which may be present on a field.
Q_GADGET Constraints constraints
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
int precision
Definition: qgsfield.h:57
int length
Definition: qgsfield.h:56
QVariant::Type type
Definition: qgsfield.h:58
QgsFieldConstraints constraints
Definition: qgsfield.h:63
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfields.cpp:371
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
Geometry collection.
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(QgsWkbTypes::Type t)
Returns empty geometry from wkb type.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Q_GADGET bool isNull
Definition: qgsgeometry.h:127
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A QTextCodec implementation which relies on OGR to do the text conversion.
static QStringList supportedCodecs()
Returns a list of supported text codecs.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
This class allows including a set of layers in a database-side transaction, provided the layer data p...
Implementation of data provider temporal properties for QgsVectorDataProviders.
This is the base class for vector data providers.
void pushError(const QString &msg) const
Push a notification about errors that happened in this providers scope.
QgsRectangle sourceExtent() const override
Returns the extent of all geometries from the source.
virtual bool cancelReload()
Cancels the current reloading of data.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
void setNativeTypes(const QList< QgsVectorDataProvider::NativeType > &nativeTypes)
Set the list of native types supported by this provider.
virtual QList< QgsRelation > discoverRelations(const QgsVectorLayer *target, const QList< QgsVectorLayer * > &layers) const
Discover the available relations with the given layers.
static QStringList availableEncodings()
Returns a list of available encodings.
virtual QString dataComment() const override
Returns a short comment for the data that this provider is providing access to (e....
@ SimplifyGeometries
Supports simplification of geometries on provider side according to a distance tolerance.
@ SimplifyGeometriesWithTopologicalValidation
Supports topological simplification of geometries on provider side according to a distance tolerance.
@ CircularGeometries
Supports circular geometry types (circularstring, compoundcurve, curvepolygon)
@ SelectAtId
Fast access to features using their ID.
@ ChangeFeatures
Supports joint updates for attributes and geometry. Providers supporting this should still define Cha...
@ ChangeGeometries
Allows modifications of geometries.
@ DeleteAttributes
Allows deletion of attributes (fields)
@ DeleteFeatures
Allows deletion of features.
@ CreateAttributeIndex
Can create indexes on provider's fields.
@ TransactionSupport
Supports transactions.
@ NoCapabilities
Provider has no capabilities.
@ AddAttributes
Allows addition of new attributes (fields)
@ CreateSpatialIndex
Allows creation of spatial index.
@ FeatureSymbology
Provider is able retrieve embedded symbology associated with individual features. Since QGIS 3....
@ RenameAttributes
Supports renaming attributes (fields). Since QGIS 2.16.
@ ChangeAttributeValues
Allows modification of attribute values.
@ AddFeatures
Allows adding features.
QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
bool supportedType(const QgsField &field) const
check if provider supports type of field
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
virtual bool changeGeometryValues(const QgsGeometryMap &geometry_map)
Changes geometries of existing features.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
virtual QgsAttrPalIndexNameHash palAttributeIndexNames() const
Returns list of indexes to names for QgsPalLabeling fix.
QgsCoordinateReferenceSystem sourceCrs() const override
Returns the coordinate reference system for features in the source.
virtual QgsFeatureRenderer * createRenderer(const QVariantMap &configuration=QVariantMap()) const
Creates a new vector layer feature renderer, using provider backend specific information.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
void clearMinMaxCache()
Invalidates the min/max cache.
virtual bool truncate()
Removes all features from the layer.
virtual bool isDeleteStyleFromDatabaseSupported() const
It returns false by default.
virtual QStringList uniqueStringsMatching(int index, const QString &substring, int limit=-1, QgsFeedback *feedback=nullptr) const
Returns unique string values of an attribute which contain a specified subset string.
void raiseError(const QString &msg) const
Signals an error in this provider.
QTextCodec * textEncoding() const
Gets this providers encoding.
void clearErrors()
Clear recorded errors.
QStringList errors() const
Gets recorded errors.
virtual bool empty() const
Returns true if the layer does not contain any feature.
QgsVectorDataProvider(const QString &uri=QString(), const QgsDataProvider::ProviderOptions &providerOptions=QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags flags=QgsDataProvider::ReadFlags())
Constructor for a vector data provider.
QList< QgsVectorDataProvider::NativeType > nativeTypes() const
Returns the names of the supported types.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual void handlePostCloneOperations(QgsVectorDataProvider *source)
Handles any post-clone operations required after this vector data provider was cloned from the source...
QgsGeometry convertToProviderType(const QgsGeometry &geom) const
Converts the geometry to the provider type if possible / necessary.
virtual bool changeFeatures(const QgsChangedAttributesMap &attr_map, const QgsGeometryMap &geometry_map)
Changes attribute values and geometries of existing features.
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of layer ids on which this layer depends.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index.
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
QgsFeatureSource::FeatureAvailability hasFeatures() const override
Will always return FeatureAvailability::FeaturesAvailable or FeatureAvailability::NoFeaturesAvailable...
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features from the provider.
QVariant maximumValue(int index) const override
Returns the maximum value of an attribute.
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QMap< QString, int > fieldNameMap() const
Returns a map where the key is the name of the field and the value is its index.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override=0
Query the provider for features specified in request.
virtual QgsAttributeList attributeIndexes() const
Returns list of indexes to fetch all attributes in nextFeature()
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes to the provider.
QVariant minimumValue(int index) const override
Returns the minimum value of an attribute.
virtual QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, int index, const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool &ok, QgsFeatureIds *fids=nullptr) const
Calculates an aggregated value from the layer's features.
void fillMinMaxCache() const
Populates the cache of minimum and maximum attribute values.
QString encoding() const
Returns the encoding which is used for accessing data.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present at the provider for a specified field index.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
virtual QgsAbstractVectorLayerLabeling * createLabeling(const QVariantMap &configuration=QVariantMap()) const
Creates labeling settings, using provider backend specific information.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
virtual bool renameAttributes(const QgsFieldNameMap &renamedAttributes)
Renames existing attributes.
virtual bool deleteAttributes(const QgsAttributeIds &attributes)
Deletes existing attributes from the provider.
virtual bool skipConstraintCheck(int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value=QVariant()) const
Returns true if a constraint check should be skipped for a specified field (e.g., if the value return...
static QVariant convertValue(QVariant::Type type, const QString &value)
bool hasErrors() const
Provider has errors to report.
QgsVectorDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QString capabilitiesString() const
Returns the above in friendly format.
Represents a vector layer which manages a vector based data sets.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:862
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:911
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
QMap< int, QString > QgsFieldNameMap
Definition: qgsattributes.h:44
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:877
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:868
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QSet< int > QgsAttributeIds
QHash< int, QString > QgsAttrPalIndexNameHash
A bundle of parameters controlling aggregate calculation.
Setting options for creating vector data providers.