Skip to content

Commit

Permalink
Distance within for HANA provider
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 5, 2021
1 parent d31c46b commit 18841ea
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 68 deletions.
160 changes: 92 additions & 68 deletions src/providers/hana/qgshanafeatureiterator.cpp
Expand Up @@ -28,6 +28,7 @@
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgssettings.h"
#include "qgsgeometryengine.h"

namespace
{
Expand Down Expand Up @@ -97,6 +98,23 @@ QgsHanaFeatureIterator::QgsHanaFeatureIterator(
return;
}

// prepare spatial filter geometries for optimal speed
switch ( mRequest.spatialFilterType() )
{
case Qgis::SpatialFilterType::NoFilter:
case Qgis::SpatialFilterType::BoundingBox:
break;

case Qgis::SpatialFilterType::DistanceWithin:
if ( !mRequest.referenceGeometry().isEmpty() )
{
mDistanceWithinGeom = mRequest.referenceGeometry();
mDistanceWithinEngine.reset( QgsGeometry::createGeometryEngine( mDistanceWithinGeom.constGet() ) );
mDistanceWithinEngine->prepareGeometry();
}
break;
}

try
{
mSqlQuery = buildSqlQuery( request );
Expand Down Expand Up @@ -151,92 +169,97 @@ bool QgsHanaFeatureIterator::fetchFeature( QgsFeature &feature )
if ( mClosed || !mResultSet )
return false;

if ( !mResultSet->next() )
return false;

feature.initAttributes( mSource->mFields.count() );
unsigned short paramIndex = 1;
while ( mResultSet->next() )
{
feature.initAttributes( mSource->mFields.count() );
unsigned short paramIndex = 1;

// Read feature id
QgsFeatureId fid = FID_NULL;
bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;
QgsAttributeList fetchAttributes = mRequest.subsetOfAttributes();
// Read feature id
QgsFeatureId fid = FID_NULL;
bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;
QgsAttributeList fetchAttributes = mRequest.subsetOfAttributes();

if ( !mSource->mPrimaryKeyAttrs.isEmpty() )
{
switch ( mSource->mPrimaryKeyType )
if ( !mSource->mPrimaryKeyAttrs.isEmpty() )
{
case QgsHanaPrimaryKeyType::PktInt:
switch ( mSource->mPrimaryKeyType )
{
int idx = mSource->mPrimaryKeyAttrs.at( 0 );
QVariant v = mResultSet->getValue( paramIndex );
if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
feature.setAttribute( idx, v );
fid = QgsHanaPrimaryKeyUtils::intToFid( v.toInt() );
++paramIndex;
}
break;
case QgsHanaPrimaryKeyType::PktInt64:
{
int idx = mSource->mPrimaryKeyAttrs.at( 0 );
QVariant v = mResultSet->getValue( paramIndex );
if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
feature.setAttribute( idx, v );
fid = mSource->mPrimaryKeyCntx->lookupFid( QVariantList( { v} ) );
++paramIndex;
}
break;
case QgsHanaPrimaryKeyType::PktFidMap:
{
QVariantList pkValues;
pkValues.reserve( mSource->mPrimaryKeyAttrs.size() );
for ( int idx : std::as_const( mSource->mPrimaryKeyAttrs ) )
case QgsHanaPrimaryKeyType::PktInt:
{
int idx = mSource->mPrimaryKeyAttrs.at( 0 );
QVariant v = mResultSet->getValue( paramIndex );
pkValues << v;
if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
feature.setAttribute( idx, v );
paramIndex++;
fid = QgsHanaPrimaryKeyUtils::intToFid( v.toInt() );
++paramIndex;
}
break;
case QgsHanaPrimaryKeyType::PktInt64:
{
int idx = mSource->mPrimaryKeyAttrs.at( 0 );
QVariant v = mResultSet->getValue( paramIndex );
if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
feature.setAttribute( idx, v );
fid = mSource->mPrimaryKeyCntx->lookupFid( QVariantList( { v} ) );
++paramIndex;
}
break;
case QgsHanaPrimaryKeyType::PktFidMap:
{
QVariantList pkValues;
pkValues.reserve( mSource->mPrimaryKeyAttrs.size() );
for ( int idx : std::as_const( mSource->mPrimaryKeyAttrs ) )
{
QVariant v = mResultSet->getValue( paramIndex );
pkValues << v;
if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
feature.setAttribute( idx, v );
paramIndex++;
}
fid = mSource->mPrimaryKeyCntx->lookupFid( pkValues );
}
fid = mSource->mPrimaryKeyCntx->lookupFid( pkValues );
}
break;
case QgsHanaPrimaryKeyType::PktUnknown:
break;
case QgsHanaPrimaryKeyType::PktUnknown:
break;
}
}
}

feature.setId( fid );
feature.setId( fid );

// Read attributes
if ( mHasAttributes )
{
for ( int idx : std::as_const( mAttributesToFetch ) )
// Read attributes
if ( mHasAttributes )
{
feature.setAttribute( idx, mResultSet->getValue( paramIndex ) );
++paramIndex;
for ( int idx : std::as_const( mAttributesToFetch ) )
{
feature.setAttribute( idx, mResultSet->getValue( paramIndex ) );
++paramIndex;
}
}
}

// Read geometry
if ( mHasGeometryColumn )
{
QgsGeometry geom = mResultSet->getGeometry( paramIndex );
if ( !geom.isNull() )
feature.setGeometry( geom );
// Read geometry
if ( mHasGeometryColumn )
{
QgsGeometry geom = mResultSet->getGeometry( paramIndex );
if ( !geom.isNull() )
feature.setGeometry( geom );
else
feature.clearGeometry();
}
else
{
feature.clearGeometry();
}
else
{
feature.clearGeometry();
}
}

feature.setValid( true );
feature.setFields( mSource->mFields ); // allow name-based attribute lookups
geometryToDestinationCrs( feature, mTransform );
geometryToDestinationCrs( feature, mTransform );
if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( feature.geometry().constGet() ) > mRequest.distanceWithin() )
{
continue;
}

return true;
feature.setValid( true );
feature.setFields( mSource->mFields ); // allow name-based attribute lookups
return true;
}
return false;
}

bool QgsHanaFeatureIterator::nextFeatureFilterExpression( QgsFeature &feature )
Expand Down Expand Up @@ -281,8 +304,9 @@ bool QgsHanaFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::Orde

QString QgsHanaFeatureIterator::buildSqlQuery( const QgsFeatureRequest &request )
{
const bool geometryRequested = ( request.flags() & QgsFeatureRequest::NoGeometry ) == 0;
bool limitAtProvider = ( request.limit() >= 0 );
const bool geometryRequested = ( request.flags() & QgsFeatureRequest::NoGeometry ) == 0
|| request.spatialFilterType() == Qgis::SpatialFilterType::DistanceWithin;
bool limitAtProvider = ( request.limit() >= 0 ) && mRequest.spatialFilterType() != Qgis::SpatialFilterType::DistanceWithin;

QgsRectangle filterRect = mFilterRect;
if ( !mSource->mSrsExtent.isEmpty() )
Expand Down
2 changes: 2 additions & 0 deletions src/providers/hana/qgshanafeatureiterator.h
Expand Up @@ -87,6 +87,8 @@ class QgsHanaFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsHa
QString mSqlQuery;
QVariantList mSqlQueryParams;
QgsRectangle mFilterRect;
QgsGeometry mDistanceWithinGeom;
std::unique_ptr< QgsGeometryEngine > mDistanceWithinEngine;
QgsAttributeList mAttributesToFetch;
QgsCoordinateTransform mTransform;
bool mHasAttributes = false;
Expand Down

0 comments on commit 18841ea

Please sign in to comment.