Branch data Line data Source code
1 : : /***************************************************************************
2 : : QgsGeoPackageProviderConnection.cpp - QgsGeoPackageProviderConnection
3 : :
4 : : ---------------------
5 : : begin : 6.8.2019
6 : : copyright : (C) 2019 by Alessandro Pasotti
7 : : email : elpaso at itopen dot it
8 : : ***************************************************************************
9 : : * *
10 : : * This program is free software; you can redistribute it and/or modify *
11 : : * it under the terms of the GNU General Public License as published by *
12 : : * the Free Software Foundation; either version 2 of the License, or *
13 : : * (at your option) any later version. *
14 : : * *
15 : : ***************************************************************************/
16 : : #include "qgsgeopackageproviderconnection.h"
17 : : #include "qgsogrdbconnection.h"
18 : : #include "qgssettings.h"
19 : : #include "qgsogrprovider.h"
20 : : #include "qgsmessagelog.h"
21 : : #include "qgsproviderregistry.h"
22 : : #include "qgsapplication.h"
23 : :
24 : 0 : QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &name )
25 : 0 : : QgsAbstractDatabaseProviderConnection( name )
26 : 0 : {
27 : 0 : mProviderKey = QStringLiteral( "ogr" );
28 : 0 : setDefaultCapabilities();
29 : 0 : QgsSettings settings;
30 : 0 : settings.beginGroup( QStringLiteral( "ogr" ), QgsSettings::Section::Providers );
31 : 0 : settings.beginGroup( QStringLiteral( "GPKG" ) );
32 : 0 : settings.beginGroup( QStringLiteral( "connections" ) );
33 : 0 : settings.beginGroup( name );
34 : 0 : setUri( settings.value( QStringLiteral( "path" ) ).toString() );
35 : 0 : }
36 : :
37 : 0 : QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &uri, const QVariantMap &configuration ):
38 : 0 : QgsAbstractDatabaseProviderConnection( uri, configuration )
39 : 0 : {
40 : 0 : mProviderKey = QStringLiteral( "ogr" );
41 : : // Cleanup the URI in case it contains other information other than the file path
42 : 0 : if ( uri.contains( '|' ) )
43 : : {
44 : 0 : setUri( uri.left( uri.indexOf( '|' ) ).trimmed() );
45 : 0 : }
46 : 0 : setDefaultCapabilities();
47 : 0 : }
48 : :
49 : 0 : void QgsGeoPackageProviderConnection::store( const QString &name ) const
50 : : {
51 : 0 : QgsSettings settings;
52 : 0 : settings.beginGroup( QStringLiteral( "ogr" ), QgsSettings::Section::Providers );
53 : 0 : settings.beginGroup( QStringLiteral( "GPKG" ) );
54 : 0 : settings.beginGroup( QStringLiteral( "connections" ) );
55 : 0 : settings.beginGroup( name );
56 : 0 : settings.setValue( QStringLiteral( "path" ), uri() );
57 : 0 : }
58 : :
59 : 0 : void QgsGeoPackageProviderConnection::remove( const QString &name ) const
60 : : {
61 : 0 : QgsSettings settings;
62 : 0 : settings.beginGroup( QStringLiteral( "ogr" ), QgsSettings::Section::Providers );
63 : 0 : settings.beginGroup( QStringLiteral( "GPKG" ) );
64 : 0 : settings.beginGroup( QStringLiteral( "connections" ) );
65 : 0 : settings.remove( name );
66 : 0 : }
67 : :
68 : 0 : QString QgsGeoPackageProviderConnection::tableUri( const QString &schema, const QString &name ) const
69 : : {
70 : 0 : const auto tableInfo { table( schema, name ) };
71 : 0 : if ( tableInfo.flags().testFlag( QgsAbstractDatabaseProviderConnection::TableFlag::Raster ) )
72 : : {
73 : 0 : return QStringLiteral( "GPKG:%1:%2" ).arg( uri(), name );
74 : : }
75 : : else
76 : : {
77 : 0 : return uri() + QStringLiteral( "|layername=%1" ).arg( name );
78 : : }
79 : 0 : }
80 : :
81 : 0 : void QgsGeoPackageProviderConnection::createVectorTable( const QString &schema,
82 : : const QString &name,
83 : : const QgsFields &fields,
84 : : QgsWkbTypes::Type wkbType,
85 : : const QgsCoordinateReferenceSystem &srs,
86 : : bool overwrite,
87 : : const QMap<QString, QVariant> *options ) const
88 : : {
89 : 0 : checkCapability( Capability::CreateVectorTable );
90 : 0 : if ( ! schema.isEmpty() )
91 : : {
92 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
93 : 0 : }
94 : 0 : QMap<QString, QVariant> opts { *options };
95 : 0 : opts[ QStringLiteral( "layerName" ) ] = QVariant( name );
96 : 0 : opts[ QStringLiteral( "update" ) ] = true;
97 : 0 : QMap<int, int> map;
98 : 0 : QString errCause;
99 : 0 : QgsVectorLayerExporter::ExportError errCode = QgsOgrProvider::createEmptyLayer(
100 : 0 : uri(),
101 : 0 : fields,
102 : 0 : wkbType,
103 : 0 : srs,
104 : 0 : overwrite,
105 : : &map,
106 : : &errCause,
107 : : &opts
108 : : );
109 : 0 : if ( errCode != QgsVectorLayerExporter::ExportError::NoError )
110 : : {
111 : 0 : throw QgsProviderConnectionException( QObject::tr( "An error occurred while creating the vector layer: %1" ).arg( errCause ) );
112 : : }
113 : 0 : }
114 : :
115 : 0 : void QgsGeoPackageProviderConnection::dropVectorTable( const QString &schema, const QString &name ) const
116 : : {
117 : 0 : checkCapability( Capability::DropVectorTable );
118 : 0 : if ( ! schema.isEmpty() )
119 : : {
120 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
121 : 0 : }
122 : 0 : QString errCause;
123 : 0 : const QString layerUri { QStringLiteral( "%1|layername=%2" ).arg( uri(), name ) };
124 : 0 : if ( ! QgsOgrProviderUtils::deleteLayer( layerUri, errCause ) )
125 : : {
126 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error deleting vector/aspatial table %1: %2" ).arg( name, errCause ) );
127 : : }
128 : 0 : }
129 : :
130 : :
131 : 0 : void QgsGeoPackageProviderConnection::dropRasterTable( const QString &schema, const QString &name ) const
132 : : {
133 : 0 : checkCapability( Capability::DropRasterTable );
134 : 0 : if ( ! schema.isEmpty() )
135 : : {
136 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
137 : 0 : }
138 : 0 : executeGdalSqlPrivate( QStringLiteral( "DROP TABLE %1" ).arg( name ) );
139 : 0 : }
140 : :
141 : :
142 : 0 : void QgsGeoPackageProviderConnection::renameVectorTable( const QString &schema, const QString &name, const QString &newName ) const
143 : : {
144 : 0 : checkCapability( Capability::RenameVectorTable );
145 : 0 : if ( ! schema.isEmpty() )
146 : : {
147 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
148 : 0 : }
149 : : // TODO: maybe an index?
150 : 0 : QString sql( QStringLiteral( "ALTER TABLE %1 RENAME TO %2" )
151 : 0 : .arg( QgsSqliteUtils::quotedIdentifier( name ),
152 : 0 : QgsSqliteUtils::quotedIdentifier( newName ) ) );
153 : 0 : executeGdalSqlPrivate( sql );
154 : 0 : sql = QStringLiteral( "UPDATE layer_styles SET f_table_name = %2 WHERE f_table_name = %1" )
155 : 0 : .arg( QgsSqliteUtils::quotedString( name ),
156 : 0 : QgsSqliteUtils::quotedString( newName ) );
157 : : try
158 : : {
159 : 0 : executeGdalSqlPrivate( sql );
160 : 0 : }
161 : : catch ( QgsProviderConnectionException &ex )
162 : : {
163 : 0 : QgsDebugMsgLevel( QStringLiteral( "Warning: error while updating the styles, perhaps there are no styles stored in this GPKG: %1" ).arg( ex.what() ), 4 );
164 : 0 : }
165 : 0 : }
166 : :
167 : 0 : QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
168 : : {
169 : 0 : checkCapability( Capability::ExecuteSql );
170 : 0 : return executeGdalSqlPrivate( sql, feedback );
171 : : }
172 : :
173 : 0 : void QgsGeoPackageProviderConnection::vacuum( const QString &schema, const QString &name ) const
174 : : {
175 : 0 : Q_UNUSED( name );
176 : 0 : checkCapability( Capability::Vacuum );
177 : 0 : if ( ! schema.isEmpty() )
178 : : {
179 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
180 : 0 : }
181 : 0 : executeGdalSqlPrivate( QStringLiteral( "VACUUM" ) );
182 : 0 : }
183 : :
184 : 0 : void QgsGeoPackageProviderConnection::createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options ) const
185 : : {
186 : 0 : checkCapability( Capability::CreateSpatialIndex );
187 : 0 : if ( ! schema.isEmpty() )
188 : : {
189 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
190 : 0 : }
191 : :
192 : 0 : QString geometryColumnName { options.geometryColumnName };
193 : 0 : if ( geometryColumnName.isEmpty() )
194 : : {
195 : : // Can we guess it?
196 : : try
197 : : {
198 : 0 : const auto tp { table( schema, name ) };
199 : 0 : geometryColumnName = tp.geometryColumn();
200 : 0 : }
201 : : catch ( QgsProviderConnectionException & )
202 : : {
203 : : // pass
204 : 0 : }
205 : 0 : }
206 : :
207 : 0 : if ( geometryColumnName.isEmpty() )
208 : : {
209 : 0 : throw QgsProviderConnectionException( QObject::tr( "Geometry column name not specified while creating spatial index" ) );
210 : : }
211 : :
212 : 0 : executeGdalSqlPrivate( QStringLiteral( "SELECT CreateSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ),
213 : 0 : QgsSqliteUtils::quotedString( ( geometryColumnName ) ) ) );
214 : 0 : }
215 : :
216 : 0 : bool QgsGeoPackageProviderConnection::spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const
217 : : {
218 : 0 : checkCapability( Capability::CreateSpatialIndex );
219 : 0 : if ( ! schema.isEmpty() )
220 : : {
221 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
222 : 0 : }
223 : 0 : const QList<QList<QVariant> > res = executeGdalSqlPrivate( QStringLiteral( "SELECT HasSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ),
224 : 0 : QgsSqliteUtils::quotedString( geometryColumn ) ) ).rows();
225 : 0 : return !res.isEmpty() && !res.at( 0 ).isEmpty() && res.at( 0 ).at( 0 ).toBool();
226 : 0 : }
227 : :
228 : 0 : void QgsGeoPackageProviderConnection::deleteSpatialIndex( const QString &schema, const QString &name, const QString &geometryColumn ) const
229 : : {
230 : 0 : checkCapability( Capability::DeleteSpatialIndex );
231 : 0 : if ( ! schema.isEmpty() )
232 : : {
233 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
234 : 0 : }
235 : 0 : executeGdalSqlPrivate( QStringLiteral( "SELECT DisableSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ),
236 : 0 : QgsSqliteUtils::quotedString( geometryColumn ) ) );
237 : 0 : }
238 : :
239 : 0 : QList<QgsGeoPackageProviderConnection::TableProperty> QgsGeoPackageProviderConnection::tables( const QString &schema, const TableFlags &flags ) const
240 : : {
241 : :
242 : : // List of GPKG quoted system and dummy tables names to be excluded from the tables listing
243 : 0 : static const QStringList excludedTableNames { { QStringLiteral( "\"ogr_empty_table\"" ) } };
244 : :
245 : 0 : checkCapability( Capability::Tables );
246 : :
247 : 0 : if ( ! schema.isEmpty() )
248 : : {
249 : 0 : QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
250 : 0 : }
251 : :
252 : 0 : QList<QgsGeoPackageProviderConnection::TableProperty> tableInfo;
253 : 0 : QString errCause;
254 : 0 : QList<QVariantList> results;
255 : :
256 : : try
257 : : {
258 : 0 : const QString sql = QStringLiteral( "SELECT c.table_name, data_type, description, c.srs_id, g.geometry_type_name, g.column_name "
259 : : "FROM gpkg_contents c LEFT JOIN gpkg_geometry_columns g ON (c.table_name = g.table_name) "
260 : 0 : "WHERE c.table_name NOT IN (%1)" ).arg( excludedTableNames.join( ',' ) );
261 : 0 : results = executeSql( sql );
262 : :
263 : 0 : for ( const auto &row : std::as_const( results ) )
264 : : {
265 : :
266 : 0 : if ( row.size() != 6 )
267 : : {
268 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: wrong number of columns returned by query" ).arg( uri() ) );
269 : : }
270 : :
271 : 0 : QgsGeoPackageProviderConnection::TableProperty property;
272 : 0 : property.setTableName( row.at( 0 ).toString() );
273 : 0 : property.setPrimaryKeyColumns( { QStringLiteral( "fid" ) } );
274 : 0 : property.setGeometryColumnCount( 0 );
275 : 0 : static const QStringList aspatialTypes = { QStringLiteral( "attributes" ), QStringLiteral( "aspatial" ) };
276 : 0 : const QString dataType = row.at( 1 ).toString();
277 : :
278 : : // Table type
279 : 0 : if ( dataType == QLatin1String( "tiles" ) || dataType == QLatin1String( "2d-gridded-coverage" ) )
280 : : {
281 : 0 : property.setFlag( QgsGeoPackageProviderConnection::Raster );
282 : 0 : }
283 : 0 : else if ( dataType == QLatin1String( "features" ) )
284 : : {
285 : 0 : property.setFlag( QgsGeoPackageProviderConnection::Vector );
286 : 0 : property.setGeometryColumn( row.at( 5 ).toString() );
287 : 0 : property.setGeometryColumnCount( 1 );
288 : 0 : }
289 : :
290 : 0 : if ( aspatialTypes.contains( dataType ) )
291 : : {
292 : 0 : property.setFlag( QgsGeoPackageProviderConnection::Aspatial );
293 : 0 : property.addGeometryColumnType( QgsWkbTypes::Type::NoGeometry, QgsCoordinateReferenceSystem() );
294 : 0 : }
295 : : else
296 : : {
297 : : bool ok;
298 : 0 : int srid = row.at( 3 ).toInt( &ok );
299 : :
300 : 0 : if ( !ok )
301 : : {
302 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error fetching srs_id table information: %1" ).arg( row.at( 3 ).toString() ) );
303 : : }
304 : :
305 : 0 : QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromEpsgId( srid );
306 : 0 : property.addGeometryColumnType( QgsWkbTypes::parseType( row.at( 4 ).toString() ), crs );
307 : 0 : }
308 : :
309 : 0 : property.setComment( row.at( 4 ).toString() );
310 : 0 : tableInfo.push_back( property );
311 : 0 : }
312 : :
313 : 0 : }
314 : : catch ( QgsProviderConnectionException &ex )
315 : : {
316 : 0 : errCause = ex.what();
317 : 0 : }
318 : :
319 : 0 : if ( ! errCause.isEmpty() )
320 : : {
321 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: %2" ).arg( uri(), errCause ) );
322 : : }
323 : : // Filters
324 : 0 : if ( flags )
325 : : {
326 : 0 : tableInfo.erase( std::remove_if( tableInfo.begin(), tableInfo.end(), [ & ]( const QgsAbstractDatabaseProviderConnection::TableProperty & ti )
327 : : {
328 : 0 : return !( ti.flags() & flags );
329 : 0 : } ), tableInfo.end() );
330 : 0 : }
331 : 0 : return tableInfo ;
332 : 0 : }
333 : :
334 : 0 : QIcon QgsGeoPackageProviderConnection::icon() const
335 : : {
336 : 0 : return QgsApplication::getThemeIcon( QStringLiteral( "mGeoPackage.svg" ) );
337 : 0 : }
338 : :
339 : 0 : void QgsGeoPackageProviderConnection::setDefaultCapabilities()
340 : : {
341 : 0 : mCapabilities =
342 : 0 : {
343 : : Capability::Tables,
344 : : Capability::CreateVectorTable,
345 : : Capability::DropVectorTable,
346 : : Capability::RenameVectorTable,
347 : : Capability::Vacuum,
348 : : Capability::Spatial,
349 : : Capability::TableExists,
350 : : Capability::ExecuteSql,
351 : : Capability::CreateSpatialIndex,
352 : : Capability::SpatialIndexExists,
353 : : Capability::DeleteSpatialIndex,
354 : : Capability::DeleteField,
355 : : Capability::AddField,
356 : : Capability::DropRasterTable
357 : : };
358 : 0 : mGeometryColumnCapabilities =
359 : 0 : {
360 : : GeometryColumnCapability::Z,
361 : : GeometryColumnCapability::M,
362 : : GeometryColumnCapability::SinglePart,
363 : : GeometryColumnCapability::Curves
364 : : };
365 : 0 : }
366 : :
367 : 0 : QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnection::executeGdalSqlPrivate( const QString &sql, QgsFeedback *feedback ) const
368 : : {
369 : :
370 : 0 : if ( feedback && feedback->isCanceled() )
371 : : {
372 : 0 : return QgsAbstractDatabaseProviderConnection::QueryResult();
373 : : }
374 : :
375 : 0 : QString errCause;
376 : 0 : gdal::ogr_datasource_unique_ptr hDS( GDALOpenEx( uri().toUtf8().constData(), GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr, nullptr, nullptr ) );
377 : 0 : if ( hDS )
378 : : {
379 : :
380 : 0 : if ( feedback && feedback->isCanceled() )
381 : : {
382 : 0 : return QgsAbstractDatabaseProviderConnection::QueryResult();
383 : : }
384 : :
385 : 0 : OGRLayerH ogrLayer( GDALDatasetExecuteSQL( hDS.get(), sql.toUtf8().constData(), nullptr, nullptr ) );
386 : :
387 : : // Read fields
388 : 0 : if ( ogrLayer )
389 : : {
390 : :
391 : 0 : auto iterator = std::make_shared<QgsGeoPackageProviderResultIterator>( std::move( hDS ), ogrLayer );
392 : 0 : QgsAbstractDatabaseProviderConnection::QueryResult results( iterator );
393 : :
394 : 0 : gdal::ogr_feature_unique_ptr fet;
395 : 0 : if ( fet.reset( OGR_L_GetNextFeature( ogrLayer ) ), fet )
396 : : {
397 : :
398 : 0 : QgsFields fields { QgsOgrUtils::readOgrFields( fet.get(), QTextCodec::codecForName( "UTF-8" ) ) };
399 : 0 : iterator->setFields( fields );
400 : :
401 : 0 : for ( const auto &f : std::as_const( fields ) )
402 : : {
403 : 0 : results.appendColumn( f.name() );
404 : : }
405 : 0 : }
406 : :
407 : : // Check for errors
408 : 0 : errCause = CPLGetLastErrorMsg( );
409 : :
410 : 0 : if ( ! errCause.isEmpty() )
411 : : {
412 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error executing SQL %1: %2" ).arg( sql, errCause ) );
413 : : }
414 : :
415 : 0 : OGR_L_ResetReading( ogrLayer );
416 : 0 : iterator->nextRow();
417 : 0 : return results;
418 : 0 : }
419 : 0 : errCause = CPLGetLastErrorMsg( );
420 : 0 : }
421 : : else
422 : : {
423 : 0 : errCause = QObject::tr( "There was an error opening GPKG %1!" ).arg( uri() );
424 : : }
425 : :
426 : 0 : if ( !errCause.isEmpty() )
427 : : {
428 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error executing SQL %1: %2" ).arg( sql, errCause ) );
429 : : }
430 : :
431 : 0 : return QgsAbstractDatabaseProviderConnection::QueryResult();
432 : 0 : }
433 : :
434 : 0 : QVariantList QgsGeoPackageProviderResultIterator::nextRowPrivate()
435 : : {
436 : 0 : const QVariantList currentRow = mNextRow;
437 : 0 : mNextRow = nextRowInternal();
438 : 0 : return currentRow;
439 : 0 : }
440 : :
441 : 0 : QVariantList QgsGeoPackageProviderResultIterator::nextRowInternal()
442 : : {
443 : 0 : QVariantList row;
444 : 0 : if ( mHDS && mOgrLayer )
445 : : {
446 : 0 : gdal::ogr_feature_unique_ptr fet;
447 : 0 : if ( fet.reset( OGR_L_GetNextFeature( mOgrLayer ) ), fet )
448 : : {
449 : 0 : if ( ! mFields.isEmpty() )
450 : : {
451 : 0 : QgsFeature f { QgsOgrUtils::readOgrFeature( fet.get(), mFields, QTextCodec::codecForName( "UTF-8" ) ) };
452 : 0 : const QgsAttributes constAttrs = f.attributes();
453 : 0 : for ( const QVariant &attribute : constAttrs )
454 : : {
455 : 0 : row.push_back( attribute );
456 : : }
457 : 0 : }
458 : : else // Fallback to strings
459 : : {
460 : 0 : for ( int i = 0; i < OGR_F_GetFieldCount( fet.get() ); i++ )
461 : : {
462 : 0 : row.push_back( QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( fet.get(), i ) ) ) );
463 : 0 : }
464 : : }
465 : 0 : }
466 : : else
467 : : {
468 : : // Release the resources
469 : 0 : GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
470 : 0 : mHDS.release();
471 : : }
472 : 0 : }
473 : 0 : return row;
474 : 0 : }
475 : :
476 : 0 : bool QgsGeoPackageProviderResultIterator::hasNextRowPrivate() const
477 : : {
478 : 0 : return ! mNextRow.isEmpty();
479 : : }
480 : :
481 : 0 : void QgsGeoPackageProviderResultIterator::setFields( const QgsFields &fields )
482 : : {
483 : 0 : mFields = fields;
484 : 0 : }
485 : :
486 : 0 : QList<QgsVectorDataProvider::NativeType> QgsGeoPackageProviderConnection::nativeTypes() const
487 : : {
488 : 0 : QgsVectorLayer::LayerOptions options { false, true };
489 : 0 : options.skipCrsValidation = true;
490 : 0 : const QgsVectorLayer vl { uri(), QStringLiteral( "temp_layer" ), QStringLiteral( "ogr" ), options };
491 : 0 : if ( ! vl.isValid() || ! vl.dataProvider() )
492 : : {
493 : 0 : const QString errorCause = vl.dataProvider() && vl.dataProvider()->hasErrors() ?
494 : 0 : vl.dataProvider()->errors().join( '\n' ) :
495 : 0 : QObject::tr( "unknown error" );
496 : 0 : throw QgsProviderConnectionException( QObject::tr( "Error retrieving native types for %1: %2" ).arg( uri(), errorCause ) );
497 : 0 : }
498 : 0 : return vl.dataProvider()->nativeTypes();
499 : 0 : }
500 : :
501 : 0 : QgsGeoPackageProviderResultIterator::~QgsGeoPackageProviderResultIterator()
502 : 0 : {
503 : 0 : if ( mHDS )
504 : : {
505 : 0 : GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
506 : 0 : }
507 : 0 : }
|