void eval_columns() { QgsFields fields; fields.append( QgsField( "x1" ) ); fields.append( QgsField( "x2" ) ); fields.append( QgsField( "foo", QVariant::Int ) ); QgsFeature f; f.initAttributes( 3 ); f.setAttribute( 2, QVariant( 20 ) ); // good exp QgsExpression exp( "foo + 1" ); bool prepareRes = exp.prepare( fields ); QCOMPARE( prepareRes, true ); QCOMPARE( exp.hasEvalError(), false ); QVariant res = exp.evaluate( &f ); QCOMPARE( res.type(), QVariant::Int ); QCOMPARE( res.toInt(), 21 ); // bad exp QgsExpression exp2( "bar + 1" ); bool prepareRes2 = exp2.prepare( fields ); QCOMPARE( prepareRes2, false ); QCOMPARE( exp2.hasEvalError(), true ); QVariant res2 = exp2.evaluate( &f ); QCOMPARE( res2.type(), QVariant::Invalid ); }
bool QgsVectorLayerImport::addFeature( QgsFeature& feat ) { QgsAttributes attrs = feat.attributes(); QgsFeature newFeat; if ( feat.constGeometry() ) newFeat.setGeometry( *feat.constGeometry() ); newFeat.initAttributes( mAttributeCount ); for ( int i = 0; i < attrs.count(); ++i ) { // add only mapped attributes (un-mapped ones will not be present in the // destination layer) int dstIdx = mOldToNewAttrIdx.value( i, -1 ); if ( dstIdx < 0 ) continue; QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 ); newFeat.setAttribute( dstIdx, attrs.at( i ) ); } mFeatureBuffer.append( newFeat ); if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE ) { return flushBuffer(); } return true; }
void RgShortestPathWidget::exportPath() { RgExportDlg dlg( this ); if ( !dlg.exec() ) return; QgsVectorLayer *vl = dlg.mapLayer(); if ( vl == NULL ) return; QgsPoint p1, p2; QgsGraph *path = getPath( p1, p2 ); if ( path == NULL ) return; QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(), vl->crs() ); int startVertexIdx = path->findVertex( p1 ); int stopVertexIdx = path->findVertex( p2 ); double time = 0.0; double cost = 0.0; Unit timeUnit = Unit::byName( mPlugin->timeUnitName() ); Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() ); QgsPolyline p; while ( startVertexIdx != stopVertexIdx ) { if ( stopVertexIdx < 0 ) break; QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc(); if ( l.empty() ) break; const QgsGraphArc& e = path->arc( l.front() ); cost += e.property( 0 ).toDouble(); time += e.property( 1 ).toDouble(); p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) ); stopVertexIdx = e.outVertex(); } p.push_front( ct.transform( p1 ) ); QgsFeature f; f.initAttributes( vl->pendingFields().count() ); f.setGeometry( QgsGeometry::fromPolyline( p ) ); f.setAttribute( 0, cost / distanceUnit.multipler() ); f.setAttribute( 1, time / timeUnit.multipler() ); QgsFeatureList features; features << f; vl->dataProvider()->addFeatures( features ); vl->updateExtents(); mPlugin->iface()->mapCanvas()->update(); delete path; }
bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { if ( mGeometrySimplifier ) mGeometrySimplifier->simplifyGeometry( geom ); // get the wkb representation int memorySize = OGR_G_WkbSize( geom ); unsigned char *wkb = new unsigned char[memorySize]; OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); QgsGeometry* geometry = feature.geometry(); if ( !geometry ) feature.setGeometryAndOwnership( wkb, memorySize ); else geometry->fromWkb( wkb, memorySize ); } if (( useIntersect && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) ) || ( geometryTypeFilter && ( !feature.geometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { OGR_F_Destroy( fet ); return false; } } if ( !mFetchGeometry ) { feature.setGeometry( 0 ); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { const QgsAttributeList& attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < mSource->mFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } return true; }
bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) const { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { feature.setGeometry( QgsOgrUtils::ogrGeometryToQgsGeometry( geom ) ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if (( useIntersect && ( !feature.hasGeometry() || !feature.geometry().intersects( mRequest.filterRect() ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { OGR_F_Destroy( fet ); return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < mSource->mFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } return true; }
bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( P->fields().count() ); feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups bool fetchGeom = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; bool geometryTypeFilter = P->mOgrGeometryTypeFilter != wkbUnknown; if ( fetchGeom || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { // get the wkb representation unsigned char *wkb = new unsigned char[OGR_G_WkbSize( geom )]; OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) ); } if (( useIntersect && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) ) || ( geometryTypeFilter && ( !feature.geometry() || wkbFlatten(( OGRwkbGeometryType )feature.geometry()->wkbType() ) != wkbFlatten( P->mOgrGeometryTypeFilter ) ) ) ) { OGR_F_Destroy( fet ); return false; } } if ( !fetchGeom ) { feature.setGeometry( 0 ); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { const QgsAttributeList& attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } return true; }
bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); if ( !mQuery ) return false; if ( !mQuery->isActive() ) { QgsDebugMsg( "Read attempt on inactive query" ); return false; } if ( mQuery->next() ) { feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups for ( int i = 0; i < mAttributesToFetch.count(); i++ ) { QVariant v = mQuery->value( i ); feature.setAttribute( mAttributesToFetch[i], mQuery->value( i ) ); } if ( mFidCol >= 0 ) { feature.setFeatureId( mQuery->value( mFidCol ).toLongLong() ); } if ( mGeometryCol >= 0 ) { QByteArray ar = mQuery->value( mGeometryCol ).toByteArray(); unsigned char* wkb = mParser.ParseSqlGeometry(( unsigned char* )ar.data(), ar.size() ); if ( wkb ) { feature.setGeometryAndOwnership( wkb, mParser.GetWkbLen() ); } } feature.setValid( true ); return true; } return false; }
void QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( P->fields().count() ); feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups // fetch geometry if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { // get the wkb representation unsigned char *wkb = new unsigned char[OGR_G_WkbSize( geom )]; OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) ); } else { feature.setGeometry( 0 ); } } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { const QgsAttributeList& attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } }
void QgsWFSFeatureIterator::copyFeature( const QgsFeature* f, QgsFeature& feature, bool fetchGeometry ) { Q_UNUSED( fetchGeometry ); if ( !f ) { return; } //copy the geometry const QgsGeometry* geometry = f->constGeometry(); if ( geometry && fetchGeometry ) { const unsigned char *geom = geometry->asWkb(); int geomSize = geometry->wkbSize(); unsigned char* copiedGeom = new unsigned char[geomSize]; memcpy( copiedGeom, geom, geomSize ); QgsGeometry *g = new QgsGeometry(); g->fromWkb( copiedGeom, geomSize ); feature.setGeometry( g ); } else { feature.setGeometry( nullptr ); } //and the attributes feature.initAttributes( mSource->mFields.size() ); for ( int i = 0; i < mSource->mFields.size(); i++ ) { const QVariant &v = f->attributes().value( i ); if ( v.type() != mSource->mFields.at( i ).type() ) feature.setAttribute( i, QgsVectorDataProvider::convertValue( mSource->mFields.at( i ).type(), v.toString() ) ); else feature.setAttribute( i, v ); } //id and valid feature.setValid( true ); feature.setFeatureId( f->id() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups }
bool QgsOgrUtils::readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields& fields, QgsFeature& feature, QTextCodec* encoding ) { // read all attributes feature.initAttributes( fields.count() ); feature.setFields( fields ); if ( !ogrFet ) return false; bool ok = false; for ( int idx = 0; idx < fields.count(); ++idx ) { QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok ); if ( ok ) { feature.setAttribute( idx, value ); } } return true; }
bool QgsGPXFeatureIterator::readRoute( const QgsRoute &rte, QgsFeature &feature ) { if ( rte.points.isEmpty() ) return false; QgsGeometry *geometry = readRouteGeometry( rte ); if ( !mFilterRect.isNull() ) { if ( ( rte.xMax < mFilterRect.xMinimum() ) || ( rte.xMin > mFilterRect.xMaximum() ) || ( rte.yMax < mFilterRect.yMinimum() ) || ( rte.yMin > mFilterRect.yMaximum() ) ) { delete geometry; return false; } if ( !geometry->intersects( mFilterRect ) ) //use geos for precise intersection test { delete geometry; return false; } } if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { feature.setGeometry( *geometry ); delete geometry; } else { delete geometry; } feature.setId( rte.id ); feature.setValid( true ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups feature.initAttributes( mSource->mFields.count() ); readAttributes( feature, rte ); return true; }
bool QgsGPXFeatureIterator::readTrack( const QgsTrack &trk, QgsFeature &feature ) { //QgsDebugMsg( QString( "GPX feature track segments: %1" ).arg( trk.segments.size() ) ); QgsGeometry *geometry = readTrackGeometry( trk ); if ( !mFilterRect.isNull() ) { if ( ( trk.xMax < mFilterRect.xMinimum() ) || ( trk.xMin > mFilterRect.xMaximum() ) || ( trk.yMax < mFilterRect.yMinimum() ) || ( trk.yMin > mFilterRect.yMaximum() ) ) { delete geometry; return false; } if ( !geometry->intersects( mFilterRect ) ) //use geos for precise intersection test { delete geometry; return false; } } if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { feature.setGeometry( *geometry ); delete geometry; } else { delete geometry; } feature.setId( trk.id ); feature.setValid( true ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups feature.initAttributes( mSource->mFields.count() ); readAttributes( feature, trk ); return true; }
bool QgsGPXFeatureIterator::readRoute( const QgsRoute& rte, QgsFeature& feature ) { if ( rte.points.size() == 0 ) return false; QgsGeometry* theGeometry = readRouteGeometry( rte ); if ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) { const QgsRectangle& rect = mRequest.filterRect(); if (( rte.xMax < rect.xMinimum() ) || ( rte.xMin > rect.xMaximum() ) || ( rte.yMax < rect.yMinimum() ) || ( rte.yMin > rect.yMaximum() ) ) return false; if ( !theGeometry->intersects( rect ) ) //use geos for precise intersection test { delete theGeometry; return false; } } if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { feature.setGeometry( theGeometry ); } else { delete theGeometry; } feature.setFeatureId( rte.id ); feature.setValid( true ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups feature.initAttributes( mSource->mFields.count() ); readAttributes( feature, rte ); return true; }
bool QgsGPXFeatureIterator::readWaypoint( const QgsWaypoint& wpt, QgsFeature& feature ) { if ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) { const QgsRectangle& rect = mRequest.filterRect(); if ( ! rect.contains( QgsPoint( wpt.lon, wpt.lat ) ) ) return false; } // some wkb voodoo if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { feature.setGeometry( readWaypointGeometry( wpt ) ); } feature.setFeatureId( wpt.id ); feature.setValid( true ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups feature.initAttributes( mSource->mFields.count() ); readAttributes( feature, wpt ); return true; }
bool QgsGPXFeatureIterator::readWaypoint( const QgsWaypoint &wpt, QgsFeature &feature ) { if ( !mFilterRect.isNull() ) { if ( ! mFilterRect.contains( QgsPointXY( wpt.lon, wpt.lat ) ) ) return false; } // some wkb voodoo if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { QgsGeometry *g = readWaypointGeometry( wpt ); feature.setGeometry( *g ); delete g; } feature.setId( wpt.id ); feature.setValid( true ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups feature.initAttributes( mSource->mFields.count() ); readAttributes( feature, wpt ); return true; }
QgsVectorLayerImport::ImportError QgsVectorLayerImport::importLayer( QgsVectorLayer* layer, const QString& uri, const QString& providerKey, const QgsCoordinateReferenceSystem *destCRS, bool onlySelected, QString *errorMessage, bool skipAttributeCreation, QMap<QString, QVariant> *options, QProgressDialog *progress ) { const QgsCoordinateReferenceSystem* outputCRS; QgsCoordinateTransform* ct = nullptr; bool shallTransform = false; if ( !layer ) return ErrInvalidLayer; if ( destCRS && destCRS->isValid() ) { // This means we should transform outputCRS = destCRS; shallTransform = true; } else { // This means we shouldn't transform, use source CRS as output (if defined) outputCRS = &layer->crs(); } bool overwrite = false; bool forceSinglePartGeom = false; if ( options ) { overwrite = options->take( "overwrite" ).toBool(); forceSinglePartGeom = options->take( "forceSinglePartGeometryType" ).toBool(); } QgsFields fields = skipAttributeCreation ? QgsFields() : layer->fields(); QGis::WkbType wkbType = layer->wkbType(); // Special handling for Shapefiles if ( layer->providerType() == "ogr" && layer->storageType() == "ESRI Shapefile" ) { // convert field names to lowercase for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx ) { fields[fldIdx].setName( fields.at( fldIdx ).name().toLower() ); } if ( !forceSinglePartGeom ) { // convert wkbtype to multipart (see #5547) switch ( wkbType ) { case QGis::WKBPoint: wkbType = QGis::WKBMultiPoint; break; case QGis::WKBLineString: wkbType = QGis::WKBMultiLineString; break; case QGis::WKBPolygon: wkbType = QGis::WKBMultiPolygon; break; case QGis::WKBPoint25D: wkbType = QGis::WKBMultiPoint25D; break; case QGis::WKBLineString25D: wkbType = QGis::WKBMultiLineString25D; break; case QGis::WKBPolygon25D: wkbType = QGis::WKBMultiPolygon25D; break; default: break; } } } QgsVectorLayerImport * writer = new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options, progress ); // check whether file creation was successful ImportError err = writer->hasError(); if ( err != NoError ) { if ( errorMessage ) *errorMessage = writer->errorMessage(); delete writer; return err; } if ( errorMessage ) { errorMessage->clear(); } QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->attributeList(); QgsFeature fet; QgsFeatureRequest req; if ( wkbType == QGis::WKBNoGeometry ) req.setFlags( QgsFeatureRequest::NoGeometry ); if ( skipAttributeCreation ) req.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator fit = layer->getFeatures( req ); const QgsFeatureIds& ids = layer->selectedFeaturesIds(); // Create our transform if ( destCRS ) ct = new QgsCoordinateTransform( layer->crs(), *destCRS ); // Check for failure if ( !ct ) shallTransform = false; int n = 0; if ( errorMessage ) { *errorMessage = QObject::tr( "Feature write errors:" ); } if ( progress ) { progress->setRange( 0, layer->featureCount() ); } // write all features while ( fit.nextFeature( fet ) ) { if ( progress && progress->wasCanceled() ) { if ( errorMessage ) { *errorMessage += '\n' + QObject::tr( "Import was canceled at %1 of %2" ).arg( progress->value() ).arg( progress->maximum() ); } break; } if ( writer->errorCount() > 1000 ) { if ( errorMessage ) { *errorMessage += '\n' + QObject::tr( "Stopping after %1 errors" ).arg( writer->errorCount() ); } break; } if ( onlySelected && !ids.contains( fet.id() ) ) continue; if ( shallTransform ) { try { if ( fet.constGeometry() ) { fet.geometry()->transform( *ct ); } } catch ( QgsCsException &e ) { delete ct; delete writer; QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" ) .arg( fet.id() ).arg( e.what() ); QgsMessageLog::logMessage( msg, QObject::tr( "Vector import" ) ); if ( errorMessage ) *errorMessage += '\n' + msg; return ErrProjection; } } if ( skipAttributeCreation ) { fet.initAttributes( 0 ); } if ( !writer->addFeature( fet ) ) { if ( writer->hasError() && errorMessage ) { *errorMessage += '\n' + writer->errorMessage(); } } n++; if ( progress ) { progress->setValue( n ); } } // flush the buffer to be sure that all features are written if ( !writer->flushBuffer() ) { if ( writer->hasError() && errorMessage ) { *errorMessage += '\n' + writer->errorMessage(); } } int errors = writer->errorCount(); if ( !writer->createSpatialIndex() ) { if ( writer->hasError() && errorMessage ) { *errorMessage += '\n' + writer->errorMessage(); } } delete writer; if ( shallTransform ) { delete ct; } if ( errorMessage ) { if ( errors > 0 ) { *errorMessage += '\n' + QObject::tr( "Only %1 of %2 features written." ).arg( n - errors ).arg( n ); } else { errorMessage->clear(); } } return errors == 0 ? NoError : ErrFeatureWriteFailed; }
bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature ) { if ( mClosed ) return false; feature.setValid( false ); int cat = -1, type = -1, id = -1; QgsFeatureId featureId = -1; QgsDebugMsgLevel( "entered.", 3 ); if ( P->isEdited() || P->isFrozen() || !P->mValid ) { close(); return false; } if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats ) { close(); return false; // No features, no features in this layer } bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid; // Get next line/area id int found = 0; while ( mNextCidx < P->mCidxFieldNumCats ) { Vect_cidx_get_cat_by_index( P->mMap, P->mCidxFieldIndex, mNextCidx++, &cat, &type, &id ); // Warning: selection array is only of type line/area of current layer -> check type first if ( !( type & P->mGrassType ) ) continue; // The 'id' is a unique id of a GRASS geometry object (point, line, area) // but it cannot be used as QgsFeatureId because one geometry object may // represent more features because it may have more categories. featureId = makeFeatureId( id, cat ); if ( filterById && featureId != mRequest.filterFid() ) continue; // it is correct to use id with mSelection because mSelection is only used // for geometry selection if ( !mSelection[id] ) continue; found = 1; break; } if ( !found ) { close(); return false; // No more features } QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 ); feature.setFeatureId( featureId ); feature.initAttributes( P->fields().count() ); feature.setFields( &P->fields() ); // allow name-based attribute lookups if ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) feature.setGeometry( 0 ); else setFeatureGeometry( feature, id, type ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) P->setFeatureAttributes( P->mLayerId, cat, &feature, mRequest.subsetOfAttributes() ); else P->setFeatureAttributes( P->mLayerId, cat, &feature ); feature.setValid( true ); return true; }
bool QgsOgrFeatureIterator::readFeature( gdal::ogr_feature_unique_ptr fet, QgsFeature &feature ) const { feature.setId( OGR_F_GetFID( fet.get() ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = !mRequest.filterRect().isNull(); bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet.get() ); if ( geom ) { QgsGeometry g = QgsOgrUtils::ogrGeometryToQgsGeometry( geom ); // Insure that multipart datasets return multipart geometry if ( QgsWkbTypes::isMultiType( mSource->mWkbType ) && !g.isMultipart() ) { g.convertToMultiType(); } feature.setGeometry( g ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if ( ( useIntersect && ( !feature.hasGeometry() || ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && !feature.geometry().intersects( mFilterRect ) ) || ( !( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) && !feature.geometry().boundingBoxIntersects( mFilterRect ) ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten( ( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.constBegin(); it != attrs.constEnd(); ++it ) { getFeatureAttribute( fet.get(), feature, *it ); } } else { // all attributes const auto fieldCount = mSource->mFields.count(); for ( int idx = 0; idx < fieldCount; ++idx ) { getFeatureAttribute( fet.get(), feature, idx ); } } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { try { feature.initAttributes( P->fields().count() ); int col = 0; if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memset( featureGeom, 0, returnedLength + 1 ); memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( P->mPrimaryKeyType ) { case QgsPostgresProvider::pktOid: case QgsPostgresProvider::pktTid: case QgsPostgresProvider::pktInt: fid = P->mConnectionRO->getBinaryInt( queryResult, row, col++ ); if ( P->mPrimaryKeyType == QgsPostgresProvider::pktInt && ( !subsetOfAttributes || fetchAttributes.contains( P->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( P->mPrimaryKeyAttrs[0], fid ); break; case QgsPostgresProvider::pktFidMap: { QList<QVariant> primaryKeyVals; foreach ( int idx, P->mPrimaryKeyAttrs ) { const QgsField &fld = P->field( idx ); QVariant v = P->convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = P->lookupFid( QVariant( primaryKeyVals ) ); } break; case QgsPostgresProvider::pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { foreach ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) getFeatureAttribute( idx, queryResult, row, col, feature ); } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { feature.initAttributes( mSource->mFields.count() ); int col = 0; if ( mFetchGeometry ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); memset( featureGeom + returnedLength, 0, 1 ); // modify 2.5D WKB types to make them compliant with OGR unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); wkbType = QgsPostgresConn::wkbTypeFromOgcWkbType( wkbType ); memcpy( featureGeom + 1, &wkbType, sizeof( wkbType ) ); // change wkb type of inner geometries if ( wkbType == QGis::WKBMultiPoint25D || wkbType == QGis::WKBMultiLineString25D || wkbType == QGis::WKBMultiPolygon25D ) { unsigned int numGeoms; memcpy( &numGeoms, featureGeom + 5, sizeof( unsigned int ) ); unsigned char *wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { unsigned int localType; memcpy( &localType, wkb + 1, sizeof( localType ) ); localType = QgsPostgresConn::wkbTypeFromOgcWkbType( localType ); memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates switch ( wkbType ) { case QGis::WKBMultiPoint25D: wkb += sizeof( double ) * 3; break; case QGis::WKBMultiLineString25D: { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( int ) + sizeof( double ) * 3 * nPoints; } break; default: case QGis::WKBMultiPolygon25D: { unsigned int nRings; memcpy( &nRings, wkb, sizeof( int ) ); wkb += sizeof( int ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( nPoints ) + sizeof( double ) * 3 * nPoints; } } break; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( mSource->mPrimaryKeyType ) { case pktOid: case pktTid: case pktInt: fid = mConn->getBinaryInt( queryResult, row, col++ ); if ( mSource->mPrimaryKeyType == pktInt && ( !subsetOfAttributes || fetchAttributes.contains( mSource->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktFidMap: { QList<QVariant> primaryKeyVals; Q_FOREACH ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields[idx]; QVariant v = QgsPostgresProvider::convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { Q_FOREACH ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < mSource->mFields.count(); ++idx )
bool QgsDelimitedTextFeatureIterator::nextFeatureInternal( QgsFeature& feature ) { QStringList tokens; QgsDelimitedTextFile *file = mSource->mFile; // If the iterator is not scanning the file, then it will have requested a specific // record, so only need to load that one. bool first = true; bool scanning = mMode == FileScan; while ( scanning || first ) { first = false; // before we do anything else, assume that there's something wrong with // the feature. If the provider is not currently valid, then cannot return // feature. feature.setValid( false ); QgsDelimitedTextFile::Status status = file->nextRecord( tokens ); if ( status == QgsDelimitedTextFile::RecordEOF ) break; if ( status != QgsDelimitedTextFile::RecordOk ) continue; // We ignore empty records, such as added randomly by spreadsheets if ( QgsDelimitedTextProvider::recordIsEmpty( tokens ) ) continue; QgsFeatureId fid = file->recordId(); while ( tokens.size() < mSource->mFieldCount ) tokens.append( QString::null ); QgsGeometry *geom = 0; // Load the geometry if required if ( mLoadGeometry ) { if ( mSource->mGeomRep == QgsDelimitedTextProvider::GeomAsWkt ) { geom = loadGeometryWkt( tokens ); } else if ( mSource->mGeomRep == QgsDelimitedTextProvider::GeomAsXy ) { geom = loadGeometryXY( tokens ); } if ( ! geom ) { continue; } } // At this point the current feature values are valid feature.setValid( true ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups feature.setFeatureId( fid ); feature.initAttributes( mSource->mFields.count() ); if ( geom ) feature.setGeometry( geom ); // If we are testing subset expression, then need all attributes just in case. // Could be more sophisticated, but probably not worth it! if ( ! mTestSubset && ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ) { const QgsAttributeList& attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator i = attrs.begin(); i != attrs.end(); ++i ) { int fieldIdx = *i; fetchAttribute( feature, fieldIdx, tokens ); } } else { for ( int idx = 0; idx < mSource->mFields.count(); ++idx ) fetchAttribute( feature, idx, tokens ); } // If the iterator hasn't already filtered out the subset, then do it now if ( mTestSubset ) { QVariant isOk = mSource->mSubsetExpression->evaluate( &feature ); if ( mSource->mSubsetExpression->hasEvalError() ) continue; if ( ! isOk.toBool() ) continue; } // We have a good record, so return return true; } return false; }
bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); if ( !mQry.isActive() ) return false; for ( ;; ) { feature.initAttributes( mSource->mFields.count() ); feature.setGeometry( 0 ); if ( mRewind ) { mRewind = false; if ( !mQry.first() ) return true; } else if ( !mQry.next() ) { return false; } int col = 0; if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 || (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && !mConnection->hasSpatial() ) ) { QByteArray *ba = static_cast<QByteArray*>( mQry.value( col++ ).data() ); unsigned char *copy = new unsigned char[ba->size()]; memcpy( copy, ba->constData(), ba->size() ); feature.setGeometryAndOwnership( copy, ba->size() ); if ( !mConnection->hasSpatial() && mRequest.filterType() == QgsFeatureRequest::FilterRect && ( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) ) { // skip feature that don't intersect with our rectangle QgsDebugMsg( "no intersect" ); continue; } if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) != 0 ) { feature.setGeometryAndOwnership( 0, 0 ); } } QgsFeatureId fid = 0; switch ( mSource->mPrimaryKeyType ) { case pktInt: // get 64bit integer from result fid = mQry.value( col++ ).toLongLong(); if ( mAttributeList.contains( mSource->mPrimaryKeyAttrs[0] ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktRowId: case pktFidMap: { QList<QVariant> primaryKeyVals; if ( mSource->mPrimaryKeyType == pktFidMap ) { foreach ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields[idx]; QVariant v = mQry.value( col ); if ( v.type() != fld.type() ) v = QgsVectorDataProvider::convertValue( fld.type(), v.toString() ); primaryKeyVals << v; if ( mAttributeList.contains( idx ) ) feature.setAttribute( idx, v ); col++; } } else { primaryKeyVals << mQry.value( col++ ); } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { try { feature.initAttributes( P->fields().count() ); int col = 0; if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memset( featureGeom, 0, returnedLength + 1 ); memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); // modify 2.5D WKB types to make them compliant with OGR unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); // convert unsupported types to supported ones switch ( wkbType ) { case 15: // 2D polyhedral => multipolygon wkbType = 6; break; case 1015: // 3D polyhedral => multipolygon wkbType = 1006; break; case 17: // 2D triangle => polygon wkbType = 3; break; case 1017: // 3D triangle => polygon wkbType = 1003; break; case 16: // 2D TIN => multipolygon wkbType = 6; break; case 1016: // TIN => multipolygon wkbType = 1006; break; } // convert from postgis types to qgis types if ( wkbType >= 1000 ) { wkbType = wkbType - 1000 + QGis::WKBPoint25D - 1; } memcpy( featureGeom + 1, &wkbType, sizeof( wkbType ) ); // change wkb type of inner geometries if ( wkbType == QGis::WKBMultiPoint25D || wkbType == QGis::WKBMultiLineString25D || wkbType == QGis::WKBMultiPolygon25D ) { unsigned int numGeoms = *(( int* )( featureGeom + 5 ) ); unsigned char* wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { unsigned int localType; memcpy( &localType, wkb + 1, sizeof( localType ) ); switch ( localType ) { case 15: // 2D polyhedral => multipolygon localType = 6; break; case 1015: // 3D polyhedral => multipolygon localType = 1006; break; case 17: // 2D triangle => polygon localType = 3; break; case 1017: // 3D triangle => polygon localType = 1003; break; case 16: // 2D TIN => multipolygon localType = 6; break; case 1016: // TIN => multipolygon localType = 1006; break; } if ( localType >= 1000 ) { localType = localType - 1000 + QGis::WKBPoint25D - 1; } memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates switch ( wkbType ) { case QGis::WKBMultiPoint25D: wkb += sizeof( double ) * 3; break; case QGis::WKBMultiLineString25D: { unsigned int nPoints = *(( int* ) wkb ); wkb += sizeof( nPoints ); wkb += sizeof( double ) * 3 * nPoints; } break; default: case QGis::WKBMultiPolygon25D: { unsigned int nRings = *(( int* ) wkb ); wkb += sizeof( nRings ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints = *(( int* ) wkb ); wkb += sizeof( nPoints ); wkb += sizeof( double ) * 3 * nPoints; } } break; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( P->mPrimaryKeyType ) { case QgsPostgresProvider::pktOid: case QgsPostgresProvider::pktTid: case QgsPostgresProvider::pktInt: fid = P->mConnectionRO->getBinaryInt( queryResult, row, col++ ); if ( P->mPrimaryKeyType == QgsPostgresProvider::pktInt && ( !subsetOfAttributes || fetchAttributes.contains( P->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( P->mPrimaryKeyAttrs[0], fid ); break; case QgsPostgresProvider::pktFidMap: { QList<QVariant> primaryKeyVals; foreach ( int idx, P->mPrimaryKeyAttrs ) { const QgsField &fld = P->field( idx ); QVariant v = P->convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = P->lookupFid( QVariant( primaryKeyVals ) ); } break; case QgsPostgresProvider::pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { foreach ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) getFeatureAttribute( idx, queryResult, row, col, feature ); } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { feature.initAttributes( mSource->mFields.count() ); int col = 0; if ( mFetchGeometry ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); memset( featureGeom + returnedLength, 0, 1 ); unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); QgsWKBTypes::Type newType = QgsPostgresConn::wkbTypeFromOgcWkbType( wkbType ); if (( unsigned int )newType != wkbType ) { // overwrite type unsigned int n = newType; memcpy( featureGeom + 1, &n, sizeof( n ) ); } // PostGIS stores TIN as a collection of Triangles. // Since Triangles are not supported, they have to be converted to Polygons const int nDims = 2 + ( QgsWKBTypes::hasZ( newType ) ? 1 : 0 ) + ( QgsWKBTypes::hasM( newType ) ? 1 : 0 ); if ( wkbType % 1000 == 16 ) { unsigned int numGeoms; memcpy( &numGeoms, featureGeom + 5, sizeof( unsigned int ) ); unsigned char *wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { const unsigned int localType = QgsWKBTypes::singleType( newType ); // polygon(Z|M) memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates unsigned int nRings; memcpy( &nRings, wkb, sizeof( int ) ); wkb += sizeof( int ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( nPoints ) + sizeof( double ) * nDims * nPoints; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( mSource->mPrimaryKeyType ) { case pktOid: case pktTid: case pktInt: fid = mConn->getBinaryInt( queryResult, row, col++ ); if ( mSource->mPrimaryKeyType == pktInt && ( !subsetOfAttributes || fetchAttributes.contains( mSource->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktFidMap: { QList<QVariant> primaryKeyVals; Q_FOREACH ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields.at( idx ); QVariant v = QgsPostgresProvider::convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { Q_FOREACH ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < mSource->mFields.count(); ++idx )
bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStatement *stmt ) { feature.setValid( false ); bool fetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; if ( mClosed ) return false; if ( !P->mConnRO || !P->mConnRO->isAlive() ) { SaDebugMsg( "No database connection." ); return false; } bool ok; int id; a_sqlany_data_value geom; unsigned char *geomBuf = NULL; ok = ( stmt != NULL && stmt->fetchNext() ); // if no more rows... if ( !ok ) return false; if ( !fetchGeometry ) feature.setGeometryAndOwnership( 0, 0 ); int numAttributes = P->fields().count(); // also used later for sanity check feature.initAttributes( numAttributes ); feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups int i = 0; int numcols = stmt->numCols(); int colidx = 0; // Refers to which column we're on in "feature" (the row) for ( i = 0; i < numcols; i++ ) { if ( i == 0 ) { // first column always contains primary key ok = stmt->getInt( i, id ); if ( !ok ) break; QgsDebugMsgLevel( QString( "pid=%1" ).arg( id ), 3 ); feature.setFeatureId( id ); } else if ( i == 1 && fetchGeometry ) { // second column contains QKB geometry value ok = stmt->getColumn( i, &geom ); if ( !ok ) break; QgsDebugMsgLevel( QString( "retrieved geometry column" ), 3 ); geomBuf = new unsigned char[ *geom.length + 1 ]; memset( geomBuf, '\0', *geom.length ); memcpy( geomBuf, geom.buffer, *geom.length ); feature.setGeometryAndOwnership( geomBuf, *geom.length + 1 ); } else { if ( i == 1 ) { feature.setGeometryAndOwnership( 0, 0 ); // no geometry to fetch } int attrIndex = subsetAttributes ? mRequest.subsetOfAttributes()[colidx++] : colidx++; QVariant val; ok = stmt->getQVariant( i, val ); // ok may be false if value was NULL, but this is a valid return // Sanity check before setting the attribute value if ( colidx - 1 == i // First column is always pk, so colidx should be at least 1 behind || ( colidx - 1 == i - 1 && fetchGeometry ) // if fetchGeometry is true, colidx should be 2 behind || attrIndex >= numAttributes ) // index should always be less than the count { SaDebugMsg( QString( "Error retrieving feature column %1 with attribute index %2" ).arg( i ).arg( attrIndex ) ); return false; } // So now this should not crash. feature.setAttribute( attrIndex, val ); } } feature.setValid( true ); return true; }
bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; feature.setValid( false ); int cat = -1, type = -1, id = -1; QgsFeatureId featureId = -1; QgsDebugMsgLevel( "entered.", 3 ); /* TODO: handle editing if ( P->isEdited() || P->isFrozen() || !P->mValid ) { close(); return false; } */ // TODO: is this necessary? the same is checked below if ( !QgsGrassProvider::isTopoType( mSource->mLayerType ) && ( mSource->mCidxFieldIndex < 0 || mNextCidx >= mSource->mCidxFieldNumCats ) ) { close(); return false; // No features, no features in this layer } bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid; // Get next line/area id int found = 0; while ( true ) { QgsDebugMsgLevel( QString( "mNextTopoId = %1" ).arg( mNextTopoId ), 3 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( mNextTopoId > Vect_get_num_lines( mSource->mMap ) ) break; id = mNextTopoId; type = Vect_read_line( mSource->mMap, 0, 0, mNextTopoId++ ); if ( !( type & mSource->mGrassType ) ) continue; featureId = id; } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { if ( mNextTopoId > Vect_get_num_nodes( mSource->mMap ) ) break; id = mNextTopoId; type = 0; mNextTopoId++; featureId = id; } else { if ( mNextCidx >= mSource->mCidxFieldNumCats ) break; Vect_cidx_get_cat_by_index( mSource->mMap, mSource->mCidxFieldIndex, mNextCidx++, &cat, &type, &id ); // Warning: selection array is only of type line/area of current layer -> check type first if ( !( type & mSource->mGrassType ) ) continue; // The 'id' is a unique id of a GRASS geometry object (point, line, area) // but it cannot be used as QgsFeatureId because one geometry object may // represent more features because it may have more categories. featureId = makeFeatureId( id, cat ); } if ( filterById && featureId != mRequest.filterFid() ) continue; // it is correct to use id with mSelection because mSelection is only used // for geometry selection if ( !mSelection[id] ) continue; found = 1; break; } if ( !found ) { close(); return false; // No more features } QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 ); feature.setFeatureId( featureId ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups if ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) feature.setGeometry( 0 ); else setFeatureGeometry( feature, id, type ); if ( ! QgsGrassProvider::isTopoType( mSource->mLayerType ) ) { if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) setFeatureAttributes( cat, &feature, mRequest.subsetOfAttributes() ); else setFeatureAttributes( cat, &feature ); } else { feature.setAttribute( 0, id ); #if GRASS_VERSION_MAJOR < 7 if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #else /* No more topo points in GRASS 7 */ if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #endif { feature.setAttribute( 1, QgsGrassProvider::primitiveTypeName( type ) ); int node1, node2; Vect_get_line_nodes( mSource->mMap, id, &node1, &node2 ); feature.setAttribute( 2, node1 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { feature.setAttribute( 3, node2 ); } } if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( type == GV_BOUNDARY ) { int left, right; Vect_get_line_areas( mSource->mMap, id, &left, &right ); feature.setAttribute( 4, left ); feature.setAttribute( 5, right ); } } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { QString lines; int nlines = Vect_get_node_n_lines( mSource->mMap, id ); for ( int i = 0; i < nlines; i++ ) { int line = Vect_get_node_line( mSource->mMap, id, i ); if ( i > 0 ) lines += ","; lines += QString::number( line ); } feature.setAttribute( 1, lines ); } } feature.setValid( true ); return true; }
bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &feature ) { bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; int ret = sqlite3_step( stmt ); if ( ret == SQLITE_DONE ) { // there are no more rows to fetch return false; } if ( ret != SQLITE_ROW ) { // some unexpected error occurred QgsMessageLog::logMessage( QObject::tr( "SQLite error getting feature: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( mHandle->handle() ) ) ), QObject::tr( "SpatiaLite" ) ); return false; } // one valid row has been fetched from the result set if ( !mFetchGeometry ) { // no geometry was required feature.setGeometryAndOwnership( 0, 0 ); } feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups int ic; int n_columns = sqlite3_column_count( stmt ); for ( ic = 0; ic < n_columns; ic++ ) { if ( ic == 0 ) { if ( mHasPrimaryKey ) { // first column always contains the ROWID (or the primary key) QgsFeatureId fid = sqlite3_column_int64( stmt, ic ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 3 ); feature.setFeatureId( fid ); } else { // autoincrement a row number mRowNumber++; feature.setFeatureId( mRowNumber ); } } else if ( mFetchGeometry && ic == mGeomColIdx ) { getFeatureGeometry( stmt, ic, feature ); } else { if ( subsetAttributes ) { if ( ic <= mRequest.subsetOfAttributes().size() ) { int attrIndex = mRequest.subsetOfAttributes()[ic-1]; feature.setAttribute( attrIndex, getFeatureAttribute( stmt, ic, mSource->mFields.at( attrIndex ).type() ) ); } } else { int attrIndex = ic - 1; feature.setAttribute( attrIndex, getFeatureAttribute( stmt, ic, mSource->mFields.at( attrIndex ).type() ) ); } } } return true; }