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 );
    }
Beispiel #2
0
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;
}
Beispiel #7
0
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
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #18
0
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;
}
Beispiel #26
0
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;
}