bool QgsTransaction::addLayer( QgsVectorLayer* layer ) { if ( !layer ) return false; if ( layer->isEditable() ) return false; //test if provider supports transactions if ( !layer->dataProvider() || ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::TransactionSupport ) == 0 ) return false; if ( layer->dataProvider()->transaction() ) return false; //connection string not compatible if ( QgsDataSourceUri( layer->source() ).connectionInfo( false ) != mConnString ) { QgsDebugMsg( QString( "Couldn't start transaction because connection string for layer %1 : '%2' does not match '%3'" ).arg( layer->id(), QgsDataSourceUri( layer->source() ).connectionInfo( false ), mConnString ) ); return false; } connect( this, &QgsTransaction::afterRollback, layer->dataProvider(), &QgsVectorDataProvider::dataChanged ); connect( QgsProject::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( onLayersDeleted( QStringList ) ) ); mLayers.insert( layer ); if ( mTransactionActive ) layer->dataProvider()->setTransaction( this ); return true; }
QgsTransaction* QgsTransaction::create( const QStringList& layerIds ) { if ( layerIds.isEmpty() ) return nullptr; QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsProject::instance()->mapLayer( layerIds.first() ) ); if ( !layer ) return nullptr; QString connStr = QgsDataSourceUri( layer->source() ).connectionInfo( false ); QString providerKey = layer->dataProvider()->name(); QgsTransaction* ts = QgsTransaction::create( connStr, providerKey ); if ( !ts ) return nullptr; Q_FOREACH ( const QString& layerId, layerIds ) { if ( !ts->addLayer( layerId ) ) { delete ts; return nullptr; } } return ts; }
bool QgsDb2Provider::setSubsetString( const QString& theSQL, bool ) { QString prevWhere = mSqlWhereClause; QgsDebugMsg( theSQL ); mSqlWhereClause = theSQL.trimmed(); QString sql = QString( "SELECT COUNT(*) FROM " ); sql += QString( "%1.%2" ).arg( mSchemaName, mTableName ); if ( !mSqlWhereClause.isEmpty() ) { sql += QString( " WHERE %1" ).arg( mSqlWhereClause ); } if ( !openDatabase( mDatabase ) ) { return false; } QSqlQuery query = QSqlQuery( mDatabase ); query.setForwardOnly( true ); QgsDebugMsg( sql ); if ( !query.exec( sql ) ) { pushError( query.lastError().text() ); mSqlWhereClause = prevWhere; QgsDebugMsg( query.lastError().text() ); return false; } if ( query.isActive() && query.next() ) { mNumberFeatures = query.value( 0 ).toInt(); QgsDebugMsg( QString( "count: %1" ).arg( mNumberFeatures ) ); } else { pushError( query.lastError().text() ); mSqlWhereClause = prevWhere; QgsDebugMsg( query.lastError().text() ); return false; } QgsDataSourceUri anUri = QgsDataSourceUri( dataSourceUri() ); anUri.setSql( mSqlWhereClause ); setDataSourceUri( anUri.uri() ); mExtent.setMinimal(); emit dataChanged(); return true; }
QgsWFSDataSourceURI::QgsWFSDataSourceURI( const QString& uri ) : mURI( uri ) { // Compatiblity with QGIS < 2.16 layer URI of the format // http://example.com/?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=x&SRSNAME=y&username=foo&password= if ( !mURI.hasParam( QgsWFSConstants::URI_PARAM_URL ) ) { QUrl url( uri ); QString srsname = url.queryItemValue( "SRSNAME" ); QString bbox = url.queryItemValue( "BBOX" ); QString typeName = url.queryItemValue( "TYPENAME" ); QString filter = url.queryItemValue( "FILTER" ); mAuth.mUserName = url.queryItemValue( QgsWFSConstants::URI_PARAM_USERNAME ); mAuth.mPassword = url.queryItemValue( QgsWFSConstants::URI_PARAM_PASSWORD ); mAuth.mAuthCfg = url.queryItemValue( QgsWFSConstants::URI_PARAM_AUTHCFG ); // Now remove all stuff that is not the core URL url.removeQueryItem( "SERVICE" ); url.removeQueryItem( "VERSION" ); url.removeQueryItem( "TYPENAME" ); url.removeQueryItem( "REQUEST" ); url.removeQueryItem( "BBOX" ); url.removeQueryItem( "SRSNAME" ); url.removeQueryItem( "FILTER" ); url.removeQueryItem( QgsWFSConstants::URI_PARAM_USERNAME ); url.removeQueryItem( QgsWFSConstants::URI_PARAM_PASSWORD ); url.removeQueryItem( QgsWFSConstants::URI_PARAM_AUTHCFG ); mURI = QgsDataSourceUri(); mURI.setParam( QgsWFSConstants::URI_PARAM_URL, url.toEncoded() ); setTypeName( typeName ); setSRSName( srsname ); //if the xml comes from the dialog, it needs to be a string to pass the validity test if ( filter.startsWith( '\'' ) && filter.endsWith( '\'' ) && filter.size() > 1 ) { filter.chop( 1 ); filter.remove( 0, 1 ); } setFilter( filter ); if ( !bbox.isEmpty() ) mURI.setParam( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX, "1" ); } else { mAuth.mUserName = mURI.param( QgsWFSConstants::URI_PARAM_USERNAME ); mAuth.mPassword = mURI.param( QgsWFSConstants::URI_PARAM_PASSWORD ); mAuth.mAuthCfg = mURI.param( QgsWFSConstants::URI_PARAM_AUTHCFG ); } }
QgsAfsProvider::QgsAfsProvider( const QString &uri ) : QgsVectorDataProvider( uri ) , mValid( false ) , mObjectIdFieldIdx( -1 ) { mSharedData.reset( new QgsAfsSharedData() ); mSharedData->mGeometryType = QgsWkbTypes::Unknown; mSharedData->mDataSource = QgsDataSourceUri( uri ); // Set CRS mSharedData->mSourceCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( mSharedData->mDataSource.param( QStringLiteral( "crs" ) ) ); // Get layer info QString errorTitle, errorMessage; const QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo( mSharedData->mDataSource.param( QStringLiteral( "url" ) ), errorTitle, errorMessage ); if ( layerData.isEmpty() ) { pushError( errorTitle + ": " + errorMessage ); appendError( QgsErrorMessage( tr( "getLayerInfo failed" ), QStringLiteral( "AFSProvider" ) ) ); return; } mLayerName = layerData[QStringLiteral( "name" )].toString(); mLayerDescription = layerData[QStringLiteral( "description" )].toString(); // Set extent QStringList coords = mSharedData->mDataSource.param( QStringLiteral( "bbox" ) ).split( ',' ); if ( coords.size() == 4 ) { bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; mSharedData->mExtent.setXMinimum( coords[0].toDouble( &xminOk ) ); mSharedData->mExtent.setYMinimum( coords[1].toDouble( &yminOk ) ); mSharedData->mExtent.setXMaximum( coords[2].toDouble( &xmaxOk ) ); mSharedData->mExtent.setYMaximum( coords[3].toDouble( &ymaxOk ) ); if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) mSharedData->mExtent = QgsRectangle(); } const QVariantMap layerExtentMap = layerData[QStringLiteral( "extent" )].toMap(); bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; QgsRectangle originalExtent; originalExtent.setXMinimum( layerExtentMap[QStringLiteral( "xmin" )].toDouble( &xminOk ) ); originalExtent.setYMinimum( layerExtentMap[QStringLiteral( "ymin" )].toDouble( &yminOk ) ); originalExtent.setXMaximum( layerExtentMap[QStringLiteral( "xmax" )].toDouble( &xmaxOk ) ); originalExtent.setYMaximum( layerExtentMap[QStringLiteral( "ymax" )].toDouble( &ymaxOk ) ); if ( mSharedData->mExtent.isEmpty() && ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) ) { appendError( QgsErrorMessage( tr( "Could not retrieve layer extent" ), QStringLiteral( "AFSProvider" ) ) ); return; } QgsCoordinateReferenceSystem extentCrs = QgsArcGisRestUtils::parseSpatialReference( layerExtentMap[QStringLiteral( "spatialReference" )].toMap() ); if ( mSharedData->mExtent.isEmpty() && !extentCrs.isValid() ) { appendError( QgsErrorMessage( tr( "Could not parse spatial reference" ), QStringLiteral( "AFSProvider" ) ) ); return; } if ( xminOk && yminOk && xmaxOk && ymaxOk ) { QgsLayerMetadata::SpatialExtent spatialExtent; spatialExtent.bounds = QgsBox3d( originalExtent ); spatialExtent.extentCrs = extentCrs; QgsLayerMetadata::Extent metadataExtent; metadataExtent.setSpatialExtents( QList< QgsLayerMetadata::SpatialExtent >() << spatialExtent ); mLayerMetadata.setExtent( metadataExtent ); } if ( extentCrs.isValid() ) { mLayerMetadata.setCrs( extentCrs ); } if ( mSharedData->mExtent.isEmpty() ) { mSharedData->mExtent = originalExtent; Q_NOWARN_DEPRECATED_PUSH mSharedData->mExtent = QgsCoordinateTransform( extentCrs, mSharedData->mSourceCRS ).transformBoundingBox( mSharedData->mExtent ); Q_NOWARN_DEPRECATED_POP }
QgsAfsProvider::QgsAfsProvider( const QString& uri ) : QgsVectorDataProvider( uri ) , mValid( false ) , mGeometryType( QgsWkbTypes::Unknown ) , mObjectIdFieldIdx( -1 ) { mDataSource = QgsDataSourceUri( uri ); // Set CRS mSourceCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( mDataSource.param( "crs" ) ); // Get layer info QString errorTitle, errorMessage; QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo( mDataSource.param( "url" ), errorTitle, errorMessage ); if ( layerData.isEmpty() ) { pushError( errorTitle + ": " + errorMessage ); appendError( QgsErrorMessage( tr( "getLayerInfo failed" ), "AFSProvider" ) ); return; } mLayerName = layerData["name"].toString(); mLayerDescription = layerData["description"].toString(); // Set extent QStringList coords = mDataSource.param( "bbox" ).split( "," ); if ( coords.size() == 4 ) { bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; mExtent.setXMinimum( coords[0].toDouble( &xminOk ) ); mExtent.setYMinimum( coords[1].toDouble( &yminOk ) ); mExtent.setXMaximum( coords[2].toDouble( &xmaxOk ) ); mExtent.setYMaximum( coords[3].toDouble( &ymaxOk ) ); if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) mExtent = QgsRectangle(); } if ( mExtent.isEmpty() ) { QVariantMap layerExtentMap = layerData["extent"].toMap(); bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; mExtent.setXMinimum( layerExtentMap["xmin"].toDouble( &xminOk ) ); mExtent.setYMinimum( layerExtentMap["ymin"].toDouble( &yminOk ) ); mExtent.setXMaximum( layerExtentMap["xmax"].toDouble( &xmaxOk ) ); mExtent.setYMaximum( layerExtentMap["ymax"].toDouble( &ymaxOk ) ); if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) { appendError( QgsErrorMessage( tr( "Could not retrieve layer extent" ), "AFSProvider" ) ); return; } QgsCoordinateReferenceSystem extentCrs = QgsArcGisRestUtils::parseSpatialReference( layerExtentMap["spatialReference"].toMap() ); if ( !extentCrs.isValid() ) { appendError( QgsErrorMessage( tr( "Could not parse spatial reference" ), "AFSProvider" ) ); return; } mExtent = QgsCoordinateTransform( extentCrs, mSourceCRS ).transformBoundingBox( mExtent ); } // Read fields foreach ( const QVariant& fieldData, layerData["fields"].toList() ) { QVariantMap fieldDataMap = fieldData.toMap(); QString fieldName = fieldDataMap["name"].toString(); QVariant::Type type = QgsArcGisRestUtils::mapEsriFieldType( fieldDataMap["type"].toString() ); if ( fieldName == "geometry" || type == QVariant::Invalid ) { QgsDebugMsg( QString( "Skipping unsupported (or possibly geometry) field" ).arg( fieldName ) ); continue; } QgsField field( fieldName, type, fieldDataMap["type"].toString(), fieldDataMap["length"].toInt() ); mFields.append( field ); } // Determine geometry type bool hasM = layerData["hasM"].toBool(); bool hasZ = layerData["hasZ"].toBool(); mGeometryType = QgsArcGisRestUtils::mapEsriGeometryType( layerData["geometryType"].toString() ); if ( mGeometryType == QgsWkbTypes::Unknown ) { appendError( QgsErrorMessage( tr( "Failed to determine geometry type" ), "AFSProvider" ) ); return; } mGeometryType = QgsWkbTypes::zmType( mGeometryType, hasZ, hasM ); // Read OBJECTIDs of all features: these may not be a continuous sequence, // and we need to store these to iterate through the features. This query // also returns the name of the ObjectID field. QVariantMap objectIdData = QgsArcGisRestUtils::getObjectIds( mDataSource.param( "url" ), errorTitle, errorMessage ); if ( objectIdData.isEmpty() ) { appendError( QgsErrorMessage( tr( "getObjectIds failed: %1 - %2" ).arg( errorTitle ).arg( errorMessage ), "AFSProvider" ) ); return; } if ( !objectIdData["objectIdFieldName"].isValid() || !objectIdData["objectIds"].isValid() ) { appendError( QgsErrorMessage( tr( "Failed to determine objectIdFieldName and/or objectIds" ), "AFSProvider" ) ); return; } mObjectIdFieldName = objectIdData["objectIdFieldName"].toString(); for ( int idx = 0, nIdx = mFields.count(); idx < nIdx; ++idx ) { if ( mFields.at( idx ).name() == mObjectIdFieldName ) { mObjectIdFieldIdx = idx; break; } } foreach ( const QVariant& objectId, objectIdData["objectIds"].toList() ) { mObjectIds.append( objectId.toInt() ); } mValid = true; }
QgsDb2Provider::QgsDb2Provider( QString uri ) : QgsVectorDataProvider( uri ) , mNumberFeatures( 0 ) , mEnvironment( ENV_LUW ) , mWkbType( QgsWkbTypes::Unknown ) { QgsDebugMsg( "uri: " + uri ); QgsDataSourceUri anUri = QgsDataSourceUri( uri ); if ( !anUri.srid().isEmpty() ) mSRId = anUri.srid().toInt(); else mSRId = -1; if ( 0 != anUri.wkbType() ) { mWkbType = anUri.wkbType(); } QgsDebugMsg( QString( "mWkbType: %1" ).arg( mWkbType ) ); QgsDebugMsg( QString( "new mWkbType: %1" ).arg( anUri.wkbType() ) ); mValid = true; mSkipFailures = false; int dim; // Not used db2WkbTypeAndDimension( mWkbType, mGeometryColType, dim ); // Get DB2 geometry type name mFidColName = anUri.keyColumn().toUpper(); QgsDebugMsg( "mFidColName " + mFidColName ); mExtents = anUri.param( "extents" ); QgsDebugMsg( "mExtents " + mExtents ); mUseEstimatedMetadata = anUri.useEstimatedMetadata(); QgsDebugMsg( QString( "mUseEstimatedMetadata: '%1'" ).arg( mUseEstimatedMetadata ) ); mSqlWhereClause = anUri.sql(); QString errMsg; mDatabase = getDatabase( uri, errMsg ); mConnInfo = anUri.connectionInfo(); QgsCoordinateReferenceSystem layerCrs = crs(); QgsDebugMsg( "CRS: " + layerCrs.toWkt() ); if ( !errMsg.isEmpty() ) { setLastError( errMsg ); QgsDebugMsg( mLastError ); mValid = false; return; } // Create a query for default connection mQuery = QSqlQuery( mDatabase ); mSchemaName = anUri.schema(); mTableName = anUri.table().toUpper(); QStringList sl = mTableName.split( '.' ); if ( sl.length() == 2 ) // Never seems to be the case { mSchemaName = sl[0]; mTableName = sl[1]; } if ( mSchemaName.isEmpty() ) { mSchemaName = anUri.username().toUpper(); } QgsDebugMsg( "mSchemaName: '" + mSchemaName + "; mTableName: '" + mTableName ); if ( !anUri.geometryColumn().isEmpty() ) mGeometryColName = anUri.geometryColumn().toUpper(); loadFields(); updateStatistics(); if ( mGeometryColName.isEmpty() ) { // table contains no geometries mWkbType = QgsWkbTypes::NoGeometry; mSRId = 0; } //fill type names into sets mNativeTypes // integer types << QgsVectorDataProvider::NativeType( tr( "8 Bytes integer" ), "bigint", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "4 Bytes integer" ), "integer", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "2 Bytes integer" ), "smallint", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (numeric)" ), "numeric", QVariant::Double, 1, 31, 0, 31 ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (decimal)" ), "decimal", QVariant::Double, 1, 31, 0, 31 ) // floating point << QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "real", QVariant::Double ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), "double", QVariant::Double ) // date/time types << QgsVectorDataProvider::NativeType( tr( "Date" ), "date", QVariant::Date, -1, -1, -1, -1 ) << QgsVectorDataProvider::NativeType( tr( "Time" ), "time", QVariant::Time, -1, -1, -1, -1 ) << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), "datetime", QVariant::DateTime, -1, -1, -1, -1 ) // string types << QgsVectorDataProvider::NativeType( tr( "Text, fixed length (char)" ), "char", QVariant::String, 1, 254 ) << QgsVectorDataProvider::NativeType( tr( "Text, variable length (varchar)" ), "varchar", QVariant::String, 1, 32704 ) << QgsVectorDataProvider::NativeType( tr( "Text, variable length large object (clob)" ), "clob", QVariant::String, 1, 2147483647 ) //DBCLOB is for 1073741824 double-byte characters, data length should be the same as CLOB (2147483647)? << QgsVectorDataProvider::NativeType( tr( "Text, variable length large object (dbclob)" ), "dbclob", QVariant::String, 1, 1073741824 ) ; }
QgsAfsProvider::QgsAfsProvider( const QString &uri, const ProviderOptions &options ) : QgsVectorDataProvider( uri, options ) { mSharedData.reset( new QgsAfsSharedData() ); mSharedData->mGeometryType = QgsWkbTypes::Unknown; mSharedData->mDataSource = QgsDataSourceUri( uri ); const QString authcfg = mSharedData->mDataSource.authConfigId(); // Set CRS mSharedData->mSourceCRS.createFromString( mSharedData->mDataSource.param( QStringLiteral( "crs" ) ) ); // Get layer info QString errorTitle, errorMessage; const QString referer = mSharedData->mDataSource.param( QStringLiteral( "referer" ) ); if ( !referer.isEmpty() ) mRequestHeaders[ QStringLiteral( "Referer" )] = referer; const QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo( mSharedData->mDataSource.param( QStringLiteral( "url" ) ), authcfg, errorTitle, errorMessage, mRequestHeaders ); if ( layerData.isEmpty() ) { pushError( errorTitle + ": " + errorMessage ); appendError( QgsErrorMessage( tr( "getLayerInfo failed" ), QStringLiteral( "AFSProvider" ) ) ); return; } mLayerName = layerData[QStringLiteral( "name" )].toString(); mLayerDescription = layerData[QStringLiteral( "description" )].toString(); // Set extent QStringList coords = mSharedData->mDataSource.param( QStringLiteral( "bbox" ) ).split( ',' ); bool limitBbox = false; if ( coords.size() == 4 ) { bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; mSharedData->mExtent.setXMinimum( coords[0].toDouble( &xminOk ) ); mSharedData->mExtent.setYMinimum( coords[1].toDouble( &yminOk ) ); mSharedData->mExtent.setXMaximum( coords[2].toDouble( &xmaxOk ) ); mSharedData->mExtent.setYMaximum( coords[3].toDouble( &ymaxOk ) ); if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) mSharedData->mExtent = QgsRectangle(); else { // user has set a bounding box limit on the layer - so we only EVER fetch features from this extent limitBbox = true; } } const QVariantMap layerExtentMap = layerData[QStringLiteral( "extent" )].toMap(); bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false; QgsRectangle originalExtent; originalExtent.setXMinimum( layerExtentMap[QStringLiteral( "xmin" )].toDouble( &xminOk ) ); originalExtent.setYMinimum( layerExtentMap[QStringLiteral( "ymin" )].toDouble( &yminOk ) ); originalExtent.setXMaximum( layerExtentMap[QStringLiteral( "xmax" )].toDouble( &xmaxOk ) ); originalExtent.setYMaximum( layerExtentMap[QStringLiteral( "ymax" )].toDouble( &ymaxOk ) ); if ( mSharedData->mExtent.isEmpty() && ( !xminOk || !yminOk || !xmaxOk || !ymaxOk ) ) { appendError( QgsErrorMessage( tr( "Could not retrieve layer extent" ), QStringLiteral( "AFSProvider" ) ) ); return; } QgsCoordinateReferenceSystem extentCrs = QgsArcGisRestUtils::parseSpatialReference( layerExtentMap[QStringLiteral( "spatialReference" )].toMap() ); if ( mSharedData->mExtent.isEmpty() && !extentCrs.isValid() ) { appendError( QgsErrorMessage( tr( "Could not parse spatial reference" ), QStringLiteral( "AFSProvider" ) ) ); return; } if ( xminOk && yminOk && xmaxOk && ymaxOk ) { QgsLayerMetadata::SpatialExtent spatialExtent; spatialExtent.bounds = QgsBox3d( originalExtent ); spatialExtent.extentCrs = extentCrs; QgsLayerMetadata::Extent metadataExtent; metadataExtent.setSpatialExtents( QList< QgsLayerMetadata::SpatialExtent >() << spatialExtent ); mLayerMetadata.setExtent( metadataExtent ); } if ( extentCrs.isValid() ) { mLayerMetadata.setCrs( extentCrs ); } if ( mSharedData->mExtent.isEmpty() ) { mSharedData->mExtent = originalExtent; Q_NOWARN_DEPRECATED_PUSH mSharedData->mExtent = QgsCoordinateTransform( extentCrs, mSharedData->mSourceCRS ).transformBoundingBox( mSharedData->mExtent ); Q_NOWARN_DEPRECATED_POP }